How can i add circular, triangle, square image overlay to UIImagepickercontroller as per above pic
and when user presses camera button then only image inside circular or triangular or square must be captured.
I have used below code but its not giving proper result. kindly see below pic.
Which is totally reverse what i want to achieve.
-(void)openCamera {
self.pickerController = [[UIImagePickerController alloc] init];
self.pickerController.delegate = self;
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
{
[self.pickerController setSourceType:UIImagePickerControllerSourceTypeCamera];
} else {
UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:#"Tatoo App" message:#"No Camera Available" delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alertView show];
}
self.pickerController.allowsEditing = NO;
self.pickerController.showsCameraControls = NO;
// creating overlayView
self.overlayView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.pickerController.view.frame.size.width-20, self.pickerController.view.frame.size.height)];
// letting png transparency be
self.overlayView .backgroundColor = [UIColor colorWithRed:0/255 green:0/255 blue:0/255 alpha:0.5];
[self.overlayView .layer setOpaque:NO];
self.overlayView .opaque = NO;
/*
UIView *circleView = [[UIView alloc]initWithFrame:CGRectMake(self.pickerController.view.frame.size.width/4, self.pickerController.view.frame.size.width/4, self.pickerController.view.frame.size.width/2, self.pickerController.view.frame.size.height/4)];
circleView.backgroundColor = [UIColor greenColor];
circleView.layer.cornerRadius = circleView.frame.size.width / 2;
circleView.clipsToBounds = YES;
[self.overlayView addSubview:circleView];
[self.overlayView bringSubviewToFront:circleView];
*/
CAShapeLayer *maskLayer = [CAShapeLayer layer];
self.overlayView.layer.mask = maskLayer;
self.maskLayer = maskLayer;
// create shape layer for circle we'll draw on top of image (the boundary of the circle)
CAShapeLayer *circleLayer = [CAShapeLayer layer];
circleLayer.lineWidth = 3.0;
circleLayer.fillColor = [[UIColor clearColor] CGColor];
circleLayer.strokeColor = [[UIColor blackColor] CGColor];
[self.overlayView.layer addSublayer:circleLayer];
self.circleLayer = circleLayer;
// create circle path
[self updateCirclePathAtLocation:CGPointMake(self.view.bounds.size.width / 2.0, self.view.bounds.size.height / 2.0) radius:self.view.bounds.size.width * 0.30];
CGFloat scale = [[self.overlayView.window screen] scale];
CGFloat radius = self.circleRadius * scale;
CGPoint center = CGPointMake(self.circleCenter.x * scale, self.circleCenter.y * scale);
CGRect frame = CGRectMake(center.x - radius,
center.y - radius,
radius * 2.0,
radius * 2.0);
// temporarily remove the circleLayer
// CALayer *circleLayer = self.circleLayer;
// [self.circleLayer removeFromSuperlayer];
// render the clipped image
UIGraphicsBeginImageContextWithOptions(self.imageOverlay.frame.size, NO, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
if ([self.overlayView respondsToSelector:#selector(drawViewHierarchyInRect:afterScreenUpdates:)])
{
// if iOS 7, just draw it
[self.overlayView drawViewHierarchyInRect:self.overlayView.bounds afterScreenUpdates:YES];
}
else
{
// if pre iOS 7, manually clip it
CGContextAddArc(context, self.circleCenter.x, self.circleCenter.y, self.circleRadius, 0, M_PI * 2.0, YES);
CGContextClip(context);
[self.overlayView.layer renderInContext:context];
}
// capture the image and close the context
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// add the circleLayer back
[self.overlayView.layer addSublayer:circleLayer];
// crop the image
CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], frame);
UIImage *croppedImage = [UIImage imageWithCGImage:imageRef];
self.takePicture = [UIButton buttonWithType:UIButtonTypeRoundedRect];
self.takePicture.frame = CGRectMake(80.0, self.pickerController.view.frame.size.height-100, 150.0, 30.0);
self.takePicture.tag = 0;
[ self.takePicture setTitle:#"Take" forState:UIControlStateNormal];
[ self.takePicture addTarget:self action:#selector(takeSnapShot:) forControlEvents:UIControlEventTouchUpInside];
[self.overlayView addSubview: self.takePicture];
self.pickerController.cameraOverlayView = self.overlayView;
[self presentViewController:self.pickerController animated:YES completion:nil];
}
Related
I am trying to create image animation on Video with the help of CAScrollLayer I am able to add images on CAScrollLayer but it's not scrolling when video is played any help will be appreciable below is my code i have tried so far.
CALayer *layer;
// self.view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
scrollLayer = [CAScrollLayer layer];
scrollLayer.backgroundColor = [[UIColor blackColor] CGColor];
scrollLayer.bounds = parentLayer.bounds;
scrollLayer.contentsRect = CGRectMake(0, 0, scrollLayer.bounds.size.width*images.count, scrollLayer.bounds.size.height);
scrollLayer.borderWidth = 2.5;
scrollLayer.borderColor = [[UIColor redColor] CGColor];
scrollLayer.position = CGPointMake(self.view.center.x, self.view.center.y - 20);
scrollLayer.scrollMode = kCAScrollHorizontally;
scrollLayer.speed = 2.0;
// [self.view.layer addSublayer:scrollLayer];
[parentLayer insertSublayer:scrollLayer atIndex:0];
for(int i=0; i<[images count]; i++) {
UIImage *image = [images objectAtIndex:i];
layer = [CALayer layer];
layer.backgroundColor = [[UIColor blackColor] CGColor];
layer.bounds = CGRectMake(0, 0, 300, 300);
layer.contents = (id)[image CGImage];
layer.position = CGPointMake(layer.bounds.size.width * i, self.view.center.y);
// scrollLayer.speed = 2.0;
[scrollLayer addSublayer:layer];
}
[parentLayer addSublayer:scrollLayer];
[self performSelector:#selector(scrollPoint) withObject:nil afterDelay:2.0];
compostion.animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer];
Thank you.
i am trying to imitate the new contact ios7 behavior.
I have a UIScrollView with a UImageView inside.
With this code i can draw the circular shape in front of the image.
-(void)viewWillAppear:(BOOL)animated
{
CGFloat screenHeight = [[UIScreen mainScreen] bounds].size.height;
int position = 0;
if (screenHeight == 568)
{
position = 124;
}
else
{
position = 80;
}
CAShapeLayer *circleLayer = [CAShapeLayer layer];
UIBezierPath *path2 = [UIBezierPath bezierPathWithOvalInRect:
CGRectMake(0.0f, position, 320.0f, 320.0f)];
[path2 setUsesEvenOddFillRule:YES];
[circleLayer setPath:[path2 CGPath]];
[circleLayer setFillColor:[[UIColor clearColor] CGColor]];
path;
path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 320, screenHeight-44) cornerRadius:0];
[path appendPath:path2];
[path setUsesEvenOddFillRule:YES];
fillLayer = [CAShapeLayer layer];
fillLayer.path = path.CGPath;
fillLayer.fillRule = kCAFillRuleEvenOdd;
fillLayer.fillColor = [UIColor blackColor].CGColor;
fillLayer.opacity = 0.8;
[self.view.layer addSublayer:fillLayer];
UILabel *moveLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 10, 320, 50)];
[moveLabel setText:#"Mueva y escale"];
[moveLabel setTextAlignment:NSTextAlignmentCenter];
[moveLabel setTextColor:[UIColor whiteColor]];
[self.view addSubview:moveLabel];
}
I need to get the portion of the image that is inside the circle when the user choose "Use Photo" option.
I wrote this category
#implementation UIImage (PathCropping)
-(UIImage *)imageCroppedWithPath:(UIBezierPath *)path
{
return [self imageCroppedWithPath:path invertPath:NO];
}
-(UIImage *)imageCroppedWithPath:(UIBezierPath *)path
invertPath:(BOOL)invertPath
{
float scaleFactor = [self scale];
CGRect imageRect = CGRectMake(0, 0, self.size.width * scaleFactor, self.size.height *scaleFactor);
CGColorSpaceRef colorSpace = CGImageGetColorSpace(self.CGImage);
CGContextRef context = CGBitmapContextCreate(NULL,
imageRect.size.width,
imageRect.size.height ,
CGImageGetBitsPerComponent(self.CGImage),
0,
colorSpace,
(CGBitmapInfo)CGImageGetAlphaInfo(self.CGImage)
);
CGContextSaveGState(context);
CGContextTranslateCTM(context, 0.0, self.size.height *scaleFactor);
CGContextScaleCTM(context, 1.0 , -1.0);
CGAffineTransform transform = CGAffineTransformMakeScale(scaleFactor, scaleFactor);
[path applyTransform:transform];
if(invertPath){
UIBezierPath *rectPath = [UIBezierPath bezierPathWithRect:imageRect];
CGContextAddPath(context, rectPath.CGPath);
CGContextAddPath(context, path.CGPath);
CGContextEOClip(context);
} else {
CGContextAddPath(context, path.CGPath);
CGContextClip(context);
}
CGContextScaleCTM(context, 1.0, -1.0);
CGContextTranslateCTM(context, 0.0, -self.size.height * scaleFactor);
CGContextDrawImage(context, imageRect, [self CGImage]);
CGImageRef imageRef = CGBitmapContextCreateImage(context);
return [UIImage imageWithCGImage:imageRef scale:scaleFactor orientation:0];
}
#end
The following image was cropped twice with the same path. once inverted, once not inverted. than I merged them again.
NSString *imageName = #"IMG_2345.jpg";
UIImage *image = [UIImage imageNamed:imageName];
UIImage *image2 = [UIImage imageNamed:imageName];
CGSize size = CGSizeMake(320, 320 * image.size.height / image.size.width);
image = [image resizedImage:size interpolationQuality:kCGInterpolationHigh];
image2 = [image2 resizedImage:size interpolationQuality:kCGInterpolationHigh];
image2 = [image2 grayscaledImage];
image = [image imageCroppedWithPath:[self circlePathWithSize: circleSize] invertPath: NO];
image2 = [image2 imageCroppedWithPath:[self circlePathWithSize: circleSize] invertPath: YES];
It is on Github
Is there any way we can make only the selected area of a superview transparent? I have a UIView with black (alpha 0.5) background color. I am putting some hollow circles on the UIView and want the underneath UIView to be transparent so that I could see through it. Any idea
- (id)initWithFrame:(CGRect)iFrame andHollowFrames:(NSArray *)iHollowFrames withRadius:(NSNumber *)iRadius {
if ((self = [super initWithFrame:iFrame]) != nil) {
self.hollowFrames = [[NSSet setWithArray:iHollowFrames] allObjects];
self.hollowCircleRadius = iRadius;
[self addShadowView];
}
return self;
}
- (void)addShadowView {
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height) cornerRadius:0];
for (NSValue *point in self.hollowFrames) {
UIBezierPath *circlePath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(point.CGPointValue.x - self.hollowCircleRadius.floatValue, point.CGPointValue.y - self.hollowCircleRadius.floatValue, 2.0 * self.hollowCircleRadius.floatValue, 2.0 * self.hollowCircleRadius.floatValue) cornerRadius:self.hollowCircleRadius.floatValue];
[path appendPath:circlePath];
}
[path setUsesEvenOddFillRule:YES];
CAShapeLayer *fillLayer = [CAShapeLayer layer];
fillLayer.path = path.CGPath;
fillLayer.fillRule = kCAFillRuleEvenOdd;
fillLayer.fillColor = [UIColor blackColor].CGColor;
fillLayer.opacity = 0.5;
[self.layer addSublayer:fillLayer];
}
Here is a UIView subclass solution. In order for this to work you must leave the superviews backgroundColor property as nil witch is the default value. If this UIView-subclass is in the storyboard then make sure you set the background color to "Clear color" in the attributes inspector.
- (void)drawRect:(CGRect)rect
{
CGContextRef ctx = UIGraphicsGetCurrentContext();
UIColor *blackBackgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5];
CGContextSetFillColorWithColor(ctx, blackBackgroundColor.CGColor);
CGContextFillRect(ctx, rect);
CGRect transparentPart = CGRectMake(10, 10, 120, 80);
CGContextClearRect(ctx, transparentPart);
}
I am using MKNetwrkKit. I have an imageView, I have added it as a subView to a UIView. I download an image using "UIImageView+MKNetworkKitAdditions.h". I add a mask to the ImageView and remove it from superView, before the download is completed, and I get a crash!
- (void) testUIImageViewDownloadCrash {
UIImageView *imageView = [[UIImageView alloc] init];
[imageView mk_setImageAtURL:[NSURL URLWithString:#"http://www.gravatar.com/avatar/a717291747c76567bb0f086e15ae6e43?s=32&d=identicon&r=PG"] onCompletion:^(BOOL success, BOOL fromCache) {
//
}];
UIView *view = [[UIView alloc] init];
[view addSubview:imageView];
[self addMaskToImageView:imageView];
[imageView removeFromSuperview];
}
Now, the weird thing is, this crash occurs only when I add the mask... here is the function that adds the mask.
- (CAGradientLayer*) addMaskToImageView:(UIImageView *) inImageView
{
CALayer *imageLayer = inImageView.layer;
CGRect imageBounds = imageLayer.bounds;
CGRect ellipseRect = CGRectInset(imageBounds, 4, 4);
CGPathRef maskPath = CGPathCreateWithEllipseInRect(ellipseRect, NULL);
if (maskPath)
{
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.bounds = imageBounds;
maskLayer.position = (CGPoint){CGRectGetMidX(imageBounds), CGRectGetMidY(imageBounds)};
maskLayer.path = maskPath;
maskLayer.fillColor = [UIColor blackColor].CGColor;
imageLayer.mask = maskLayer;
CFRelease(maskPath);
}
CAGradientLayer *gradientRingLayer = [self createGradientRing:imageBounds];
CALayer *containerLayer = [CALayer layer];
[imageLayer.superlayer addSublayer:containerLayer];
// Move container layer to the image position
containerLayer.position = imageLayer.position;
// Image is now at 0,0 in the container
imageLayer.position = CGPointZero;
[containerLayer addSublayer:gradientRingLayer];
[containerLayer addSublayer:imageLayer];
layer.shouldRasterize = YES;
layer.rasterizationScale = [[UIScreen mainScreen] scale];
layer.contentsScale = [[UIScreen mainScreen] scale];
containerLayer.shadowColor = [UIColor blackColor].CGColor;
containerLayer.shadowOpacity = 1.0f;
containerLayer.shadowOffset = CGSizeMake(2.0f, 5.0f);
containerLayer.shadowRadius = 7.5f;
// Create shadow at the righ place around the image
CGPathRef containerShadowPath = CGPathCreateWithEllipseInRect(imageLayer.frame, NULL);
containerLayer.shadowPath = containerShadowPath;
CFRelease(containerShadowPath);
return gradientRingLayer;
}
- (CAGradientLayer*)createGradientRing:(CGRect)inBounds {
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.anchorPoint = CGPointMake(0.5f, 0.5f);
gradient.position = CGPointMake(0.0f, 0.0f);
// gradient.startPoint = CGPointMake(0.0,0.0);
// gradient.endPoint = CGPointMake(0.0,0.0);
gradient.bounds = inBounds;
gradient.cornerRadius = 0.0;
gradient.colors = [NSArray arrayWithObjects:
(id)[UIColor ringLight].CGColor,
(id)[UIColor ringLight].CGColor,
nil];
CAShapeLayer *frameLayer = [CAShapeLayer layer];
CGPathRef framePath = CGPathCreateWithEllipseInRect(CGRectInset(inBounds, 0, 0), NULL);
if (framePath)
{
frameLayer.bounds = inBounds;
frameLayer.position = (CGPoint){CGRectGetMidX(inBounds), CGRectGetMidY(inBounds)};
frameLayer.path = framePath;
frameLayer.fillColor = [UIColor blackColor].CGColor;
CFRelease(framePath);
}
gradient.mask = frameLayer;
return gradient;
}
If I comment out adding the mask, it won't crash. Another thing that I don't understand is, after adding the mask, if do this:
NSLog(#"subviews count : %i",[view.subviews count]);
then I get 0! Where did the imageView go?
I observed that the addMask function is making a superView of the imageView null. I found out that the line [containerLayer addSublayer:imageLayer]; is the culprit. This is making the superView of the imageView null. But why? And how can I fix it?
Sometimes I get this exception too, and I don't know why.
-[__NSCFString sublayers]: unrecognized selector sent to instance
I tried on iOS 5 and iOS 6.
I'm trying to create a UIbutton that has the following characteristics:
* A custom image as its content
* Rounded corners
* A drop shadow
Using the following code will format the button to appear correctly and function but the highlight action (i.e., the darkening of the button when touched) is lost when the touch occurs. Any ideas?
+(void) styleButton:(UIButton*)button{
UIView *backgroundView = [[UIView alloc] initWithFrame:CGRectMake(button.bounds.origin.x, button.bounds.origin.y, button.bounds.size.width, button.bounds.size.height)];
CALayer *sublayer = [CALayer layer];
sublayer.shadowOffset = CGSizeMake(0, 3);
sublayer.shadowRadius = 5.0;
sublayer.shadowColor = [UIColor blackColor].CGColor;
sublayer.shadowOpacity = 0.8;
sublayer.frame = CGRectMake(button.bounds.origin.x, button.bounds.origin.y, button.bounds.size.width, button.bounds.size.height);
backgroundView.userInteractionEnabled = NO;
[backgroundView.layer addSublayer:sublayer];
[button insertSubview:backgroundView atIndex:0];
CALayer *imageLayer = [CALayer layer];
imageLayer.frame = sublayer.bounds;
imageLayer.cornerRadius = 10.0;
imageLayer.contents = (id) [UIImage imageNamed:#"myImage.png"].CGImage;
imageLayer.cornerRadius = 5.0f;
imageLayer.masksToBounds = YES;
[sublayer addSublayer:imageLayer];
}
Have you tried converting your backgroundView into a UIImage and add it to the button instead of adding backgroundView as a subview? That would preserve the darkening when the button is pressed:
UIGraphicsBeginImageContext(backgroundView.frame.size);
[backgroundView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[button setImage:image forState:UIControlStateNormal];
Like this (ARC enabled):
UIGraphicsBeginImageContextWithOptions(self.button.bounds.size, NO, [[UIScreen mainScreen] scale]);
CGContextRef context = UIGraphicsGetCurrentContext();
for (UIView *aView in self.button.subviews) {
CGContextSaveGState(context);
CGContextTranslateCTM(context, aView.frame.origin.x, aView.frame.origin.y);
[aView.layer renderInContext:UIGraphicsGetCurrentContext()];
CGContextRestoreGState(context);
}
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[self.button setImage:image forState:UIControlStateNormal];
[self.button.subviews makeObjectsPerformSelector:#selector(removeFromSuperview)];
[self.button setAdjustsImageWhenHighlighted:YES];