I am creating an image from free hand drawing using below code :
UIGraphicsBeginImageContext(self.bounds.size);
for (UIBezierPath *path in self.pathArray) {
[self.lineColor setStroke];
[path stroke];
}
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
I want to take image of only black lines (drawing) not the entire view's. View is size of 300x300. But if my drawing is in 50x50 then I want to focus on that part only.
I tried with
UIGraphicsBeginImageContext(signPath.bounds.size);
signPath is UIBezierPath object. But with this I am getting blank image.
Any suggestions ?
ok I figured it out.
UIGraphicsBeginImageContext(signPath.bounds.size);
By this way I was creating image context's size only and origin was missing.
So I need to create image context with x and y (origins).
I have origin in UIBezierPath with size.
Code :
CGSize size = signPath.bounds.size;
size = CGSizeMake(size.width + 10, size.height + 10);
UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);
CGContextRef c = UIGraphicsGetCurrentContext();
CGContextConcatCTM(c, CGAffineTransformMakeTranslation(-signPath.bounds.origin.x + 5, -signPath.bounds.origin.y + 5));
[self.layer renderInContext:c];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
I have given static values for some padding (given some space) while creating the image.
Not sure if this is the standard way, but it solved my problem and I am able to create image of hand drawing in a 500x500 view.
Now I am getting image of the my free hand drawing (Strokes) not for the entire view.
Related
I want to draw a circle on UIImageView. I have tried it but it didn't work.
This is a example image of what i want to achieve:
The circle should be drawn on where user taps on UIImageView and I want to do it without adding any sublayer.
Is it some way to do this?
so far i have used this code from the internet but it didn't worked.
- (UIImage *)imageByDrawingCircleOnImage:(UIImage *)image
pointX:(float) x
PointY:(float) y
{
// begin a graphics context of sufficient size
UIGraphicsBeginImageContext(image.size);
// draw original image into the context
[image drawAtPoint:CGPointZero];
// get the context for CoreGraphics
CGContextRef ctx = UIGraphicsGetCurrentContext();
// set stroking color and draw circle
[[UIColor redColor] setStroke];
// make circle rect 5 px from border
CGRect circleRect = CGRectMake(0, 0,
image.size.width,
image.size.height);
circleRect = CGRectInset(circleRect, x, y);
// draw circle
CGContextStrokeEllipseInRect(ctx, circleRect);
// make image out of bitmap context
UIImage *retImage = UIGraphicsGetImageFromCurrentImageContext();
// free the context
UIGraphicsEndImageContext();
return retImage;
}
Suppose your object's view is square, Set the cornerRadius to half of the width or height.
maskToBounds set your image as per shape of rounded imageView
For example,add this code for your requirement,
yourImageView.layer.cornerRadius = yourImageView.imageView.frame.size.height /2;
yourImageView.layer.masksToBounds = YES;
Hope this will help you :)
![enter image description here][1]By using the following code, I am able to draw a large image in small form, But new one image have their superview context or in other other word new image show in centre of new image but have a large white background to cover up large imageSize.
So, Actual image size is same as large image but I want to remove the extra white space.
UIGraphicsBeginImageContextWithOptions(largeImage.size, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
[[UIColor clearColor] setFill];
CGContextSetLineWidth(context, 4.0);
CGContextSetStrokeColorWithColor(context,
[UIColor clearColor].CGColor);
CGRect rectangle = CGRectMake((largeImage.size.width-80)/2, (largeImage.size.height-60)/2, 60, 80);
CGContextAddEllipseInRect(context, rectangle);
CGContextStrokePath(context);
[largeImage drawInRect:rectangle];
UIImage *smallSizeImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Finally , I am getting smallSizeimage with a lot of white background. I want to change their white background without loosing the image quality.
Please guide me..
You are over-complicating the process mate.
I will post below an explanation to your problem,
Since I'm not a native english speaker, if some of my explanations aren't really clear, tell me, and I'll try to rephrase them.
If you are just interested in a working code, without any of my explanations, just scroll to the bottom.
First of all, your main issues are the following two:
UIGraphicsBeginImageContextWithOptions(largeImage.size, NO, 0); and [largeImage drawInRect:rectangle];
In UIGraphicsBeginImageContextWithOptions you suppose to set the new graphics context you are interested in, meaning, the new image size, and not the large one, as you are doing in your example.
Second, the UIImage instance method [yourImage drawInRect:yourRect is in your coordinate system of the graphics context, and not the coordinate system of the view.
Meaning, you suppose to treat it as a rectangle which begins at (0, 0) and is the size of your image.
After explaining to you the mistakes you've had, I'll post 2 variations of code.
One is to make a small image out of your original one, which you'll see in a second how much of a simple process that is.
And the second one is a modified version of your code above, since I don't know what you are using it to, could be that you do need the use of some of the other things from you original code.
To resize an image:
CGSize newSize = CGSizeMake(60,80); // Our new image size
CGRect newRect = CGRectMake(0, 0, 60, 80); // Our 'work' rect in out image context
// Begin a new image context with the new size we want
UIGraphicsBeginImageContextWithOptions(newSize, NO, 0);
// Draw our image to our new rect
[largeImage drawInRect:newRect];
// Create a new UIImage from our new context
UIImage *smallImage = UIGraphicsGetImageFromCurrentImageContext();
// End our image context
UIGraphicsEndImageContext();
And that's it!
If you still need to use some of the stuff from your original code, Here is a modified version of it:
CGSize newSize = CGSizeMake(60, 80);
CGRect newRect = CGRectMake(0, 0, 60, 80);
UIGraphicsBeginImageContextWithOptions(newSize, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
[[UIColor clearColor] setFill];
CGContextSetLineWidth(context, 4.0);
CGContextSetStrokeColorWithColor(context,
[UIColor clearColor].CGColor);
CGContextAddEllipseInRect(context, newRect);
CGContextClip(context); // EDIT- this is what we were missing
CGContextStrokePath(context);
[largeImage drawInRect:newRect];
UIImage *smallSizeImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Good luck mate!
EDIT- Check out the code above for the edit.
Basically, what you and I have both missed in your code, is that, even tough you create a rounded context by using CGContextAddEllipseInRect(), we don't have a call to CGContextClip() to actually 'clipping' the context in our ellipse shape.
Now your image should be 'rounded'.
Replace this
UIGraphicsBeginImageContextWithOptions(largeImage.size, NO, 0);
with this:
UIGraphicsBeginImageContextWithOptions(small.size, NO, 0);
Furhermore here it is a method that i call to resize images:
- (UIImage*)imageWithImage:(UIImage*)image
{
CGSize newSize=CGSizeMake(100, 100);
UIGraphicsBeginImageContext( newSize );
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
I think I may have an odd request, however hopefully someone can help. I am using the well known UIScrollView + UIImageView to zoom into and out of an image, as well as pan. This works fine and dandy, but the current project we have needs to be able to crop the image, but also include the black bars on the sides if the image is smaller than the crop rectangle. See the images below.
We wish to capture everything inside of the blue box, including the white (which will be black, since opaque is set to YES).
This works great for images that are completely zoomed out (The white is just the UIImageView's extra space).
However the problem arises when we try to zoom into the image, and capture only that portion, plus the empty space.
This results in the following image
The problem we are seeing is we need to be able to create an image that is exactly what is in the Crop Rect, regardless if there is part of the image there or not. The other problem is we wish to have the ability to dynamically change the output resolution. The aspect ratio is 16:9, and for this example kMaxWidth = 1136 and kMaxHeight = 639, however in the future we may want to request a larger or smaller 16:9 resolution.
Below is the function I have so far:
- (UIImage *)createCroppedImageFromImage:(UIImage *)image {
CGSize newRect = CGSizeMake(kMaxWidth, kMaxHeight);
UIGraphicsBeginImageContextWithOptions(newRect, YES, 0.0);
// 0 is the edge of the screen, to help with zooming
CGFloat xDisplacement = ((abs(0 - imageView.frame.origin.x) * kMaxWidth) / (self.cropSize.width / self.scrollView.zoomScale) / self.scrollView.zoomScale);
CGFloat yDisplacement = ((abs(self.cropImageView.frame.origin.y - imageView.frame.origin.y) * kMaxHeight) / (self.cropSize.height / self.scrollView.zoomScale) / self.scrollView.zoomScale);
CGFloat newImageWidth = (self.image.size.width * kMaxWidth) / (self.cropSize.width / self.scrollView.zoomScale);
CGFloat newImageHeight = (self.image.size.height * kMaxHeight) / (self.cropSize.height / self.scrollView.zoomScale);
[image drawInRect:CGRectMake(xDisplacement, 0, newImageWidth, newImageHeight)];
UIImage *croppedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return croppedImage;
}
Any help would be greatly appreciated.
I ended up just taking a screenshot, and cropping that. It seems to work well enough.
- (UIImage *)cropImage {
CGRect cropRect = self.cropOverlay.cropRect;
UIGraphicsBeginImageContext(self.view.frame.size);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *fullScreenshot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGImageRef croppedImage = CGImageCreateWithImageInRect(fullScreenshot.CGImage, cropRect);
UIImage *crop = [[UIImage imageWithCGImage:croppedImage] resizedImage:self.outputSize interpolationQuality:kCGInterpolationHigh];
CGImageRelease(croppedImage);
return crop;
}
If using iOS 7, you would use drawViewHierarchyInRect:afterScreenUpdates:, instead of renderInContext:
I think the translated rect for the image view isn't calculated properly. Since UIImageView is the subview inside the UIScrollView, you should be able to calculate the visible rect by calling [scrollView convertRect:scrollView.bounds toView:imageView];. That will be the visible rect of your image view. All you need to now is crop it.
-(UIImage*)cropImage:(UIImage*)img inRect:(CGRect)rect{
CGImageRef cropped = CGImageCreateWithImageInRect(img.CGImage, rect);
UIImage *image = [UIImage imageWithCGImage:cropped];
CGImageRelease(cropped);
return image;
}
Edit: Yeah... I forgot to mention that cropping should be done in (0,1) coordinate space. I've modified the crop function for you, so it crops the image based on all parameters you provided, UIImageView inside UIScrollView and an image.
-(UIImage*)cropImage:(UIImage*)image inImageView:(UIImageView*)imageView scrollView:(UIScrollView*)scrollView{
// get visible rect from image scrollview
CGRect visibleRect = [scrollView convertRect:scrollView.bounds toView:imageView];
UIImage* rCroppedImage;
CALayer* maskLayer= [[CALayer alloc] init];
maskLayer.contents= (id)image.CGImage;
maskLayer.frame= CGRectMake(0, 0, visibleRect.size.width, visibleRect.size.height);
CGRect rect= CGRectMake(visibleRect.origin.x / image.size.width,
visibleRect.origin.y / image.size.height,
visibleRect.size.width / image.size.width,
visibleRect.size.height / image.size.height);
maskLayer.contentsRect= rect;
UIGraphicsBeginImageContext(visibleRect.size);
CGContextRef context= UIGraphicsGetCurrentContext();
[maskLayer renderInContext:context];
rCroppedImage= UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return rCroppedImage;
}
I have been trying to experiment with clipping an image in a circular path. But, I can't seem to get the clipping path to be anti-aliased.
I have tried a few different things, but none seem to work. How do I get the clipped image to be anti-aliased?
UIImage*originalImage = [UIImage imageNamed:#"grandpa.png"];
int minWidth = originalImage.size.width;
bool isWidth = YES;
if(minWidth > originalImage.size.height){
minWidth = originalImage.size.height;
isWidth = NO;
}
UIBezierPath *path;
if(isWidth)
path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, (originalImage.size.height - minWidth)/2, minWidth, minWidth)];
else
path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake((originalImage.size.width - minWidth)/2, 0, minWidth, minWidth)];
UIGraphicsBeginImageContextWithOptions(originalImage.size, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetAllowsAntialiasing(context, true);
CGContextSetShouldAntialias(context, true);
[path addClip];
[originalImage drawAtPoint:CGPointZero];
UIImage *maskedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//This is based on the full size image
CGRect imageRect = CGRectMake(0, 0, maskedImage.size.width + 2, maskedImage.size.height + 2);
UIGraphicsBeginImageContext(imageRect.size);
[maskedImage drawInRect:CGRectMake(1,1,maskedImage.size.width,maskedImage.size.height)];
maskedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
I had this problem and it took me several hours on google and debugging but I finally figured this one out.
Whats happening is when you set the maskedImage to your imageView.image there is some resizing going on which includes the rounded clipping (on the image) and the result comes out funky.
A small example would be if your imageView has a bounds of 100x100 and the maskedImage has a bounds of 300x300 then when the imageView.image sets the maskedImage there will be reduced resizing to fit the image. This reduced sizing wont updated the rounded clipping, so your result is what appears to be jagged edges. If before you add the rounded clipping you scale the maskedImage to a size close to the imageView then your rounded edges will look exactly how you want!
I have an jpg Image with a round object in a rect and want to make the envoirement of the round object transparent...
(Remove red area in this example)
With the help of this iOS make part of an UIImage transparent and "UIBezierPath bezierPathWithOvalInRect" i've got a little success, but this make a path around my object, and I need to invert it, to make the outside and not the inside of the path transparent..
Im not shure where I have to change my code to get the right result..
Here is my code:
//BezierPath
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 100, 100)];
// Create an image context containing the original UIImage.
UIGraphicsBeginImageContext(_imgTemp.image.size);
[_imgTemp.image drawAtPoint:CGPointZero];
// Clip to the bezier path and clear that portion of the image.
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextAddPath(context,bezierPath.CGPath);
CGContextClip(context);
CGContextClearRect(context,CGRectMake(0,0,self._imgTemp.image.size.width,self._imgTemp.image.size.height));
// Build a new UIImage from the image context.
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self._imgTemp.image = newImage;
Anybody got the resolving?
To only draw within the black circle you should move [_imgTemp.image drawAtPoint:CGPointZero]; to after CGContextClip(context); and then remove the CGContextClearRect( ... ) call entirely:
//BezierPath
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 100, 100)];
// Create an image context containing the original UIImage.
UIGraphicsBeginImageContext(_imgTemp.image.size);
// Clip to the bezier path and clear that portion of the image.
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextAddPath(context,bezierPath.CGPath);
CGContextClip(context);
// Draw here when the context is clipped
[_imgTemp.image drawAtPoint:CGPointZero];
// Build a new UIImage from the image context.
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self._imgTemp.image = newImage;