How can I place an image behind an imageView - iphone

I've got an image which contains multiple layers. The user can set a picture as a layer. However when there isn't a picture available I'd like to have a replacement picture.
I think I got two options:
check if the image (taken photo) is loaded into my directory. if not place the other image.
placing the other image (photo_icon.png) to the back of the UIImageView (image1). When a photo hasn't been taken the image becomes visible.
Here's a snippit of my code so far.
NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *pngFilePath = [NSString stringWithFormat:#"%#/photo1.png",docDir];
UIImage *img = [[UIImage alloc] initWithContentsOfFile:pngFilePath];
[image1 setImage:img];
image1.layer.cornerRadius = 15.0;
image1.layer.masksToBounds = YES;
CALayer *sublayer = [CALayer layer];
image1.layer.borderColor = [UIColor blackColor].CGColor;
image1.layer.borderWidth = 3.5;
[image1.layer addSublayer:sublayer];
CALayer *imageLayer = [CALayer layer];
imageLayer.frame = image1.bounds;
imageLayer.cornerRadius = 10.0;
imageLayer.contents = (id) [UIImage imageNamed:#"Upperlayer.png"].CGImage;
imageLayer.masksToBounds = YES;
[sublayer addSublayer:imageLayer];
replacing the image1 for the image which is needed I use:
CALayer *imageBackLayer = [CALayer layer];
imageBackLayer.frame = image1.bounds;
imageBackLayer.cornerRadius = 10.0;
imageBackLayer.contents = (id) [UIImage imageNamed:#"photo_icon.png"].CGImage;
imageBackLayer.masksToBounds = NO;
[sublayer insertSublayer:imageBackLayer below: image1.layer ];
Thanks in advance!

you can use opacity for the image to show/hide.

Related

Paged UIScrollView with UIImageViews only showing first UIImageVIew

I am working on a paged UIScrollView, but it only wants to show the first UIImageView within it. I add each UIImageView at an offset of the width of the scroll view, so that should create each page. When run, it says the scroll view is the right number of pages, but the images don't show.
Any help would be much appreciated!
int numSlides = NUM_TUTORIAL_SLIDES;
NSString *fileName;
UIImageView *slideImageView;
CGRect slideFrame;
for (int i = 1; i <= numSlides; i++)
{
slideFrame.origin.x = self.tutorialScrollView.frame.size.width * (i-1);
slideFrame.origin.y = 0;
slideFrame.size = self.tutorialScrollView.frame.size;
slideImageView = [[UIImageView alloc] initWithFrame:slideFrame];
if([[AppManager sharedManager] is4inchScreen])
{
fileName = [NSString stringWithFormat:#"Slide%d4in#2x.png", i];
}
else
{
fileName = [NSString stringWithFormat:#"Slide%d#2x.png", i];
}
slideImageView.image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:fileName ofType:nil]];
[self.tutorialScrollView addSubview:slideImageView];
[slideImageView release];
}
self.tutorialScrollView.contentSize = CGSizeMake(self.tutorialScrollView.frame.size.width * numSlides, self.tutorialScrollView.frame.size.height);
self.tutorialScrollView.delegate = self;
Maybe change the following code will help
slideImageView.image = [UIImage imageNamed:fileName];
Turns out that the issue had to do with rounding the corners of the scroll view.
I had this code:
//Round header image
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.tutorialScrollView.bounds
byRoundingCorners:(UIRectCornerTopLeft | UIRectCornerTopRight)
cornerRadii:CGSizeMake(DEFAULT_CORNER_RADIUS_HEADER, DEFAULT_CORNER_RADIUS_HEADER)];
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.path = maskPath.CGPath;
self.tutorialScrollView.layer.mask = maskLayer;
and apparently that causes issues with the scroll view

Adding a mask with CALayers

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

CALayer - backgroundColor flipped?

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.

Aligning Background Within a CALayer

I'm trying to create a UIImage from an image context and set that as the contents of a CALayer (the image will end up split up and spread across multiple CALayers). The only problem is, it doesn't seem to be aligning correctly - it's offset by 30 pixels or so.
- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
number = 1;
background = [UIImage imageNamed:#"numberBackground.png"];
// draw images
UIGraphicsBeginImageContext(CGSizeMake(background.size.width, background.size.height));
[background drawAtPoint:CGPointMake(0, 0)];
NSString *numberString = [[NSString alloc] initWithString:[NSString stringWithFormat:#"%d", number]];
[[UIColor whiteColor] set];
[numberString drawAtPoint:CGPointMake(0, 0) withFont:[UIFont fontWithName:#"HelveticaNeue" size:128]];
UIImage *front = [UIGraphicsGetImageFromCurrentImageContext() retain];
UIGraphicsEndImageContext();
// top layer
topLayer = [CALayer layer];
[topLayer setContents:(id)front.CGImage];
[topLayer setContentsGravity:#"kCAGravityTop"];
[topLayer setFrame:CGRectMake(0, 0, background.size.width, background.size.height / 2)];
[topLayer setAnchorPoint:CGPointMake(0, 1)];
[topLayer setPosition:CGPointMake(0, background.size.height / 2)];
[topLayer setMasksToBounds:NO];
[topLayer setBackgroundColor:[UIColor lightGrayColor].CGColor];
[self.layer addSublayer:topLayer];
}
return self;
}
I don't have enough reputation points to post an image yet, but here's how the layer renders, as well as how it should render and the full image: link text
Found my mistake - setContentsGravity should take the built-in string constant kCAGravityTop, not my NSString literal #"kCAGravityTop".

Load entire image and use CATiledLayer

I'm not sure I did understand that very well in the Apple doc. I'm considering using CATiledLayer to display a JPEG image. However, I only have an entire JPEG file at my disposal and no small tiles. Is it still possible to use a CATiledLayer and let it "tile" the JPEG?
Thanks!
No. You will have to tile them yourself, unfortunately. The WWDC 2010 videos on Core Animation discuss how to do this and in their sample code, they demonstrate how to use a CATileLayer when the tiles already exist.
Correction
I meant to say watch the Scroll View session. It's session 104 "Designing Apps with Scroll Views"
You may use This for making CATileLayer with image and Zoom functionality in scrollview.
- (void)viewDidLoad
{
[super viewDidLoad];
// You do not need to and must not autorelease [NSBundle mainBundle]
NSString *path = [[NSBundle mainBundle] pathForResource:#"img" ofType:#"jpg"];
NSData *data = [NSData dataWithContentsOfFile:path];
image = [UIImage imageWithData:data];
// CGRect pageRect = CGRectMake(0, 0, 1600, 2400);
CGRect pageRect = CGRectMake(0.0, 0.0, image.size.width, image.size.height);
CATiledLayer *tiledLayer = [CATiledLayer layer];
tiledLayer.delegate = self;
tiledLayer.tileSize = CGSizeMake(256.0, 256.0);
tiledLayer.levelsOfDetail = 5; // was 1000, which makes no sense. Each level of detail is a power of 2.
tiledLayer.levelsOfDetailBias = 5; // was 1000, which also makes no sense.
// Do not change the tiledLayer.frame.
tiledLayer.bounds = pageRect; // I think you meant bounds instead of frame.
// Flip the image vertically.
tiledLayer.transform = CATransform3DMakeScale(1.0f, -1.0F, 1.0f);
myContentView = [[UIView alloc] initWithFrame:CGRectMake(500,400,image.size.width,image.size.height)];
[myContentView.layer addSublayer:tiledLayer];
// UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
scrollView=[[UIScrollView alloc]initWithFrame:CGRectMake(10, 10, 300, 400)];
scrollView.backgroundColor = [UIColor whiteColor];
// [scrollView setContentSize:CGSizeMake(image.size.width,image.size.height)];
[scrollView setContentSize:image.size];
scrollView.maximumZoomScale = 32; // = 2 ^ 5
scrollView.delegate = self;
// scrollView.contentSize = pageRect.size;
[scrollView addSubview:myContentView];
[self.view addSubview:scrollView];
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return myContentView;
}
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context
{
NSString *path = [[NSBundle mainBundle] pathForResource:#"img" ofType:#"jpg"];
NSData *data = [NSData dataWithContentsOfFile:path];
image = [UIImage imageWithData:data];
CGRect imageRect = CGRectMake (0.0, 0.0, image.size.width, image.size.height);
CGContextDrawImage (context, imageRect, [image CGImage]);
}
The easier way is to just downscale the image until it fits (I think devices support up to 2044x2044 or so). You can create subimages of a CGImage with CGImageCreateWithImageInRect()