CALayer Position Contents to Bottom Left - objective-c

I am attempting to draw an image onto a CALayer. I only need an image, so I have created my later as follows:
CALayer *layer = [CALayer layer];
I add my image as follows:
NSImage *img = [[NSImage alloc] initWithContentsOfFile:#"path/to/img.png"];
[layer setContents:img];
This works, however it draws my images to fill the entire parent frame (stretching my image in the process).
Reading the docs, I found the following:
[layer setContentsGravity:#"kCAGravityBottomLeft"];
I am attempting to draw my image in the bottom left of the parent frame, however no matter what I do it draws my icon in the bottom center. Is there anyway to specify the bottom left?

Try this:
CALayer *layer = [CALayer layer];
layer.contentsGravity = kCAGravityBottomLeft;
layer.contents = (id) aCGImageRef;
Note that kCAGravityBottomLeft is declared as NSString and the contents property expects a CGImageRef.

Related

Rotate NSImage around its vertical axis

I am trying to rotate the NSImage around the vertical axis, saving the result. The main purpose is to generate an array of frames of the same image with different rotation degrees. I need to have that array to modify each frame separately. The desired result for a single frame is the following:
So far I was trying to use CATransform3DRotate to make a single rotated NSImage, but I am not able to apply this transform to NSImage in any way. I tried applying CATransform3DRotate to a newly created CALayer and even to a layer of a specially created view, the best I can get is the same picture, as before.
CATransform3D t = CATransform3DRotate(CATransform3DIdentity, (60 * M_PI / 180), 0, 1, 0);
CALayer *layer = [CALayer layer];
[layer setFrame: imageRect];
[layer setContents:image];
[layer setTransform:t];
NSImage * newImage = [[NSImage alloc] initWithSize:layer.bounds.size];
[newImage lockFocus];
[layer renderInContext:[NSGraphicsContext currentContext].CGContext];
[newImage unlockFocus];
This code results in newImage being the same non-rotated image. I tried some other ways too, but none of them succeed.
Maybe there is an easier way to achieve my aim (generate the array of rotation frames of the same NSImage), but I have no idea, what it is.
NSImage object cannot be rotated. You need to rotate a view or layer and then save the contents of the view/layer as an image.
See Saving an NSView to a png file? for how to save a view as image.

how to add shadow to only the bottom and right side of a uiview?

I am thinking about adding drop shadow to the bottom and right side of UIView, but I found all the solutions out there are adding shadows for four sides a view. Is there a way to work around that?
You can use CAGradientLayer like so,
CAGradientLayer *shadow = [CAGradientLayer layer];
shadow.frame = CGRectMake(-10, 0, 10, myView.frame.size.height);
shadow.startPoint = CGPointMake(1.0, 0.5);
shadow.endPoint = CGPointMake(0, 0.5);
shadow.colors = [NSArray arrayWithObjects:(id)[[UIColor colorWithWhite:0.0 alpha:0.4f] CGColor], (id)[[UIColor clearColor] CGColor], nil];
[myView.layer addSublayer:shadow];
You'll have to change the frame to suit your needs. This example displays a shadow along the height of a view on the left. You can also change the start and end point to control the direction of the shadow.
I may do it by adding two UIImageViews with stretched shadow image on bottom and right side of the view. You don't have to cover all the view with those UIImageViews, you just clip as much as you need. Take a look at the color blended layers of twitter on the iPhone, I believe those beautiful shadows are created by using UIImageViews. And that saves system resources. Of course you can use CALayer to create shadow, but I think it consumes more system resources to render the shadow, so CALayer is second choice for me.
UIBezierPath *shadowPath = [UIBezierPath
bezierPathWithRect:self.yourViewObj.bounds];
self.yourViewObj.layer.masksToBounds = NO;
self.yourViewObj.layer.shadowColor = [UIColor blackColor].CGColor;//*** color you want for shadow
self.yourViewObj.layer.shadowOffset = CGSizeMake(5.0f, 5.0f);
self.yourViewObj.layer.shadowOpacity = 0.7f;
self.yourViewObj.layer.shadowPath = shadowPath.CGPath;

CALayer Audio Indicator with Mask

Ok, What I want to do is create an audio indicator, basically overlay a mask or layer onto an image with a background color and opacity... so it looks like a red level indicator is bouncing up and down overtop of a microphone image, I got this to work in a very poor way updating the image each time with a UIImage mask but this was very inefficient.
Im trying to get it to work now with a CALayer which it does and better than the first trial and error way I tried. The problem now is Im only showing a rectangle and the corresponding level with it. I want it to be bounded by the microphone image, so it looks half full for instance, when I mask to bounds the rectangle takes the shape of the microphone and jumps up and down in that shape instead of "filling" the image.
Hopefully this isn't too confusing, I hope you can understand the premise and help!! Here is some code I have working now, in the wrong way:
self.image = [UIImage imageNamed:#"img_icon_microphone.png"];
CALayer *maskLayer = [CALayer layer];
maskLayer.frame = CGRectMake(0.f, 0.f, 200.f, 200.f);
maskLayer.contents = (id) [UIImage imageNamed:#"img_icon_microphone.png"].CGImage;
micUpdateLayer = [CALayer layer];
micUpdateLayer.frame = CGRectMake(0.f, 200.f, 200.f, -5.f);
micUpdateLayer.backgroundColor = [UIColor redColor].CGColor;
micUpdateLayer.opacity = 0.5f;
[self.layer addSublayer:micUpdateLayer];
Im then just using a NSTimer and a call to a function which simply updates the micUpdateLayer.frame y to make it appear to be moving with the audio input.
Thank you for any suggestions!

ios: Screenshot doesn't display mask Layer

I have a view with a certain background color. I am masking this view with the following code:
UIView *colorableView = [[UIView* alloc] init];
colorableView.backgroundColor = someColor;
CALayer *maskLayer = [CALayer layer];
maskLayer.contents = (id)[UIImage imageNamed:maskImageName].CGImage;
colorableView.layer.mask = maskLayer;
Ok everything works fine there. The view gets masked, so some parts are transparent. Now I make a screenshot of this view:
CGRect frame = colorableView.frame;
UIGraphicsBeginImageContext(frame.size);
CGContextRef c = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(someUninterestingCodeToGetACorrectPosition);
[self.view.layer renderInContext:c];
UIImage *screenShotImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return screenShotImage;
Taking a screenshot works (actually I display some other stuff above the view too and that gets displayed in the screenshot as well), but somehow, the mask is not recognized. Meaning what I get is a screenshot of a fully colored view (a rectangle) without the mask hiding some parts of it.
I guess ´UIGraphicsGetImageFromCurrentImageContext()`doesn't work with mask layers, so what can I do about it? I need to have a UIImage to display the screenshot in a mail.
Thanks a lot in advance
One way to fix this can be to use Quartz functions to clip the view (CGContextClip, I don't remember exactly, you'll have to dig a little bit into the documentation).
Hope this will help

When I set the anchor point, my image is not loading

I have a UIView on which i am loading my image view as a sub view. The image is showing when i doesn't set the anchor point but whenever i set anchor point the image is not showing .I have added the QUARTZCore frame work also.
I am adding my code below
CGRect apprect=CGRectMake(0, 0, 1024, 768);
UIView *containerView = [[UIView alloc] initWithFrame:apprect1];
containerView.backgroundColor = [UIColor whiteColor];
[self.view addSubview:containerView];
handleView1= [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"large.gif"]];
[handleView1 setAlpha:1];
//[handleView1 setFrame:CGRectMake(390, 172.00, 56.00, 316.00)];
handleView1.userInteractionEnabled = YES;
handleView1.layer.anchorPoint=CGPointMake(490.0, 172.0);
[containerView addSubview:handleView1];
The problem are the values you use for the anchorPoint. You don't set points like for the position of a frame as values. Let me quote Apple:
The anchorPoint property is a CGPoint
that specifies a location within the
bounds of a layer that corresponds
with the position coordinate. The
anchor point specifies how the bounds
are positioned relative to the
position property, as well as serving
as the point that transforms are
applied around. It is expressed in
the unit coordinate system-the
(0.0,0.0) value is located closest to
the layer’s origin and (1.0,1.0) is
located in the opposite corner.
Have a look at Layer Geometry and Transforms in the Core Animation Programming Guide for more details.
First set the Frame of your ImageView and then set the ancherpoint like this
[ handleView1.layer setAnchorPoint:CGPointMake(1, 1)];