I seem to be having difficulties adding a mask via CALayers. I'm simply trying to mask a UIImageView. Here's my code:
CALayer *maskLayer = [CALayer layer];
UIImage *mask = [UIImage imageNamed:#"mask.png"];
maskLayer.contents = mask;
UIImageView *viewToMask = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)];
viewToMask.image = [UIImage imageNamed:#"picture.png"];
viewToMask.layer.mask = maskLayer;
[self.view addSubview:viewToMask];
Mask.png is black with a transparent circle punched through it (is this correct way to mask?). I'm not sure where this is failing, perhaps at maskLayer.contents since its supposed to be a CGImageRef but I get errors when I set it as mask.CGImage, or through a local variable CGImageRef = mask.CGImage. Anyway, the way its set now doesn't give errors, so I hope its fine.
Does anyone know what's going on, or how to properly set masks with CALayers? Thanks
Try
maskLayer.contents = (id)mask.CGImage;
Yes, the cast sucks, but it's necessary.
I think you'll also need to say
maskLayer.bounds = (CGRect){CGPointZero, mask.size};
try this:
CALayer *maskLayer = [CALayer layer];
UIImage *mask = [UIImage imageNamed:#"mask.png"];
maskLayer.contents = (id)mask.CGImage;
// maskLayer.contentsGravity = kCAGravityCenter;
maskLayer.frame = CGRectMake(0.0, 0.0,1024,768);
UIImageView *viewToMask = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)];
viewToMask.image = [UIImage imageNamed:#"picture.png"];
viewToMask.layer.mask = maskLayer;
[self.view addSubview:viewToMask];
you also need to set mask frame
Related
well I know that every imageViews have a layer (we can access it with :imageView.layer).I would like to use the layer of my imageView and add a subLayer to it's layer:shapeLayer(that is a CAShapeLayer) My code doesn't work, it doesn't show the shape layer!
- (void)viewDidLoad
{
imageView = [[UIImageView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
[self.view addSubview:imageView];
}
- (void)anotherMethod
{
[imageView.layer addSublayer:shapeLayer];
}
How can I solve this please ?
Try this:
[outputImage.layer insertSublayer:shapeLayer atIndex:0];
I solved similar problem by using UIView below UIImageView and setting a layer to UIView. When you add a layer to UIImageView at index 0, your image will not be visible.
I have a UIView called photoView. It has a subview of class UIImageView, that has same bounds and has a clear background color. And I add a gradientLayer to photoView.
- (void)viewDidLoad
{
[super viewDidLoad];
// Adding gradient background to UIImageView
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = self.photoImageView.bounds;
gradientLayer.colors = #[(id)[UIColor customUltraLightGrayColor].CGColor, (id)[UIColor customUltraLightGrayColor].CGColor, (id)[UIColor customDarkGrayColor].CGColor];
gradientLayer.locations = #[#(0.0), #(0.6)];
[self.photoView.layer insertSublayer:gradientLayer atIndex:0];
}
As a result I get this:
This could have several reasons, for example:
Did you #import <QuartzCore/QuartzCore.h> (and / or CoreGraphics/CoreGraphics.h> depending on what you are doing in the rest of your code)?
You could have set a wrong CGRectMake when initializing the CALayer which is not inside your visible frame (Like CGRectMake(5000,5000,...,...)) or one of the size properties is 0?
Try setting the frame for layer:
Follow the three steps
CALayer layerToBeAdded = [[CALayer alloc] init];
[layerToBeAdded setFrame:imgView.frame];
[imgView.layer addSublayer:layerToBeAdded];
Instead of allocating CALayer, you can use [imgView layer]
And to add image to layer do it like this
layerToBeAdded.contents = (id)imgXYZ.CGImage;
Assuming that you are talking about just one UIImageView (imageView == outputImage ???)
//in another method:
{
[imageView.layer addSublayer:shapeLayer]; //Where is outputImage initialized?
}
Here is a solution:
CALayer *pulseLayer_ = [[CALayer layer] retain];
pulseLayer_.backgroundColor = [[UIColor whiteColor] CGColor];
pulseLayer_.bounds = CGRectMake(0., 0., 80., 80.);
pulseLayer_.cornerRadius = 12.;
pulseLayer_.position = self.view.center;
[self.view.layer addSublayer:pulseLayer_];
CALayer *imageLayer = [CALayer layer];
imageLayer.frame = pulseLayer_.bounds;
imageLayer.cornerRadius = 10.0;
imageLayer.contents = (id) [UIImage imageNamed:#"jacklogo.png"].CGImage;
imageLayer.masksToBounds = YES;
[pulseLayer_ addSublayer:imageLayer];
[pulseLayer_ setNeedsDisplay];
I'm creating a CALayer like this:
UIColor *color = [UIColor colorWithPatternImage:[UIImage imageNamed:#"MyPattern.png"]];
backgroundLayer = [[CALayer alloc] init];
[backgroundLayer setBackgroundColor:[color CGColor]];
[[self layer] addSublayer:backgroundLayer];
For some reason, the pattern is drawn upside down. I've already tried setting geometryFlipped and applying sublayer transforms, but it doesn't work.
Using [backgroundLayer setTransform:CATransform3DMakeScale(1.0, -1.0, 1.0)]; actually does work.
I would rather use this method:
CALayer *backgroundLayer = [CALayer layer];
backgroundLayer.frame = CGRectMake(50, 50, 200, 200);
UIImage *img = [UIImage imageNamed:#"MyPattern.png"];
CGImageRef imgRef = CGImageRetain(img.CGImage);
backgroundLayer.contents = (id) imgRef;
[self.layer addSublayer:backgroundLayer];
This will provide image content inside the layer and it fits automatically, so it works great for backgrounds. Im not sure why your method isnt working, sorry about that, but I thought it would be nice to provide you with this method.
Instead of using CATransform3DMakeScale you can flip image yourself:
UIImage* img = [UIImage imageNamed:#"MyPattern.png"];
img = [UIImage imageWithCGImage:img.CGImage
scale:img.scale
orientation:UIImageOrientationDownMirrored];
UIColor* color = [UIColor colorWithPatternImage:img];
…
This works fine for me.
Or you can go further and actually redraw the image.
- (UIImage*)flipImage:(UIImage*)image {
UIGraphicsBeginImageContext(image.size);
CGContextDrawImage(UIGraphicsGetCurrentContext(),CGRectMake(0.,0., image.size.width, image.size.height),image.CGImage);
UIImage* img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
Details why it can be useful are in this answer.
I am trying to distort an image in an arbitrary way, following for example a bezier shape. I have used CAShapeLayer to create the shape, but then it seems that setting its contents to an Image does not work. How can I have the image distorted following that shape? Is it even possible?
Thank you!
it is not possible to do so, but i succeeded in doing so by putting a CALayer on top a CAShapeLayer.
this is my code:
CALayer *image =[CALayer layer];
image.frame = CGRectMake(0, 0, 75, 75);
image.contents = (id) [UIImage imageNamed:#"number-1"].CGImage;
[self.layer addSublayer:image];
UIBezierPath *circle = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 75, 75)];
blueCircleLayer = [CAShapeLayer layer];
blueCircleLayer.path = circle.CGPath;
blueCircleLayer.strokeColor = [UIColor blueColor].CGColor;
blueCircleLayer.fillColor = [UIColor clearColor].CGColor;
blueCircleLayer.shadowColor =[UIColor blackColor].CGColor;
blueCircleLayer.shadowOffset = CGSizeMake(0.0f, 5.0f);
blueCircleLayer.shadowOpacity = 0.7f;
blueCircleLayer.lineWidth = 7.0;
[self.layer addSublayer:blueCircleLayer];
This is currently not possible. I would suggest filing a radar (http://bugreport.apple.com) if you think this should be supported.
See also: Can a CGImage be added to the contents property of a CAShapeLayer?
I am trying to create a drop shadow for an image. I also have an animation between views and this is the backdrop. However, when I use the following code, the image is not drawn. Anyone have any ideas?
self.frontViewBackground = [[[UIView alloc] initWithFrame:frame] autorelease];
//self.frontViewBackground.image = [UIImage imageNamed:#"whitepaper3.png"];
self.frontViewBackground.multipleTouchEnabled = YES;
[self.photoView addSubview:self.frontViewBackground];
UIImage *image = [UIImage imageNamed:#"whitepaper3.png"];
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetShadow(ctx, CGSizeMake(1, -2), 3.0);
[image drawInRect:self.frontViewBackground.frame blendMode:kCGBlendModeNormal alpha:1.0];
CGContextRestoreGState(ctx);
Have you thought about using CALayer's shadow properties? For example you could do the following:
UIView *view = [[UIView alloc] initWithFrame:frame];
view.layer.shadowColor = [[UIColor blackColor] CGColor];
view.layer.shadowRadius = 5.0
Check out more here: http://developer.apple.com/iphone/library/documentation/GraphicsImaging/Reference/CALayer_class/Introduction/Introduction.html#//apple_ref/occ/instp/CALayer/shadowColor
According to the Mac Dev Center docs, you should be able to set the contents property of a CALayer and have that render automatically. However, I still can't get a simple image to show up by adding a sublayer to the UIView's root later. I've tried multiple different variations; here's what I have so far:
(Note: I know there are other ways of rendering images; for my purposes I'd like to use CALayer's for some of the more complicated stuff I'm going to get into).
(in viewDidDisplay() of the ViewController):
CALayer *theLayer = [CALayer layer];
[[[self view] layer] addSublayer:theLayer];
theLayer.contents = (id)[[UIImage imageNamed:#"mypic.png"] CGImage];
theLayer.contentsRect = CGRectMake(0.0f, 0.0f, 300.0f, 300.0f);
theLayer.bounds = CGRectMake(0.0f, 0.0f, 300.0f, 400.0f);
Anyone know what I'm doing wrong?
Thanks!
You could load the image into a UIImageView, which is decended from UIView and therefore has it's own layer property.
UIImageView *imgView = [[UIImageView alloc] initWithFrame:frame];
imgView.image = [UIImage imageNamed:#"mypic.png"];
[[[self view] layer] addSublayer:[imgView layer]];
[imgView release];
You don't need to set the contentsRect (and if you do, it should be in the unit coordinate space, probably just CGRectMake(0, 0, 1.0, 1.0).
You might want to set the layer's position property.
You need to create two CALayer . This is perfect way to display the image within the CALayer.
CALayer *pulseLayer_ = [[CALayer layer] retain];
pulseLayer_.backgroundColor = [[UIColor whiteColor] CGColor];
pulseLayer_.bounds = CGRectMake(0., 0., 80., 80.);
pulseLayer_.cornerRadius = 12.;
pulseLayer_.position = self.view.center;
[self.view.layer addSublayer:pulseLayer_];
CALayer *imageLayer = [CALayer layer];
imageLayer.frame = pulseLayer_.bounds;
imageLayer.cornerRadius = 10.0;
imageLayer.contents = (id) [UIImage imageNamed:#"jacklogo.png"].CGImage;
imageLayer.masksToBounds = YES;
[pulseLayer_ addSublayer:imageLayer];
[pulseLayer_ setNeedsDisplay];
I think its make solution to your problem.