PDA

View Full Version : Layering an image over another




RossOliver
Apr 22, 2008, 09:52 PM
Hey,

I want to try some image manipulation. The effect I'm after is similar to that of the Delicious Library images; a solid image as an overlay to another image - in their case they put an image of a book cover over a base image, which gives it a book-looking texture.

How would I go about replicating these effects?

Thanks,

-Ross



RossOliver
Apr 22, 2008, 11:04 PM
I think I have what I need now:

http://developer.apple.com/documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_images/chapter_12_section_7.html#//apple_ref/doc/uid/TP30001066-CH212-CJBEBCAA

What's the best way to go about this? I have two NSImage objects at the minute and I want to overlay one on top of the other. Is there a relatively straight forward example of this knocking around that anyone knows of? I can't seem to find any good documentation on how it all fits together...

-Ross

RossOliver
Apr 23, 2008, 10:35 AM
I have a working program now doing what I want. I made it by subclassing UIView, adding a UIImageView subview containing the bottom image I want to use and then added the image I wanted on top of it in the drawRect method:


-( id )initWithItemUnderlay:( UIImage * )itemUnderlay frame:( CGRect )frame
{
if( self = [super initWithFrame:frame] )
{
UIImageView *imageView = [[UIImageView alloc] initWithImage: itemUnderlay];
[self addSubview:imageView];
[imageView release];
overlayImage = NO;
}
return self;
}

-( void )drawRect:( CGRect )rect
{
if( overlayImage )
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextDrawImage( context, rect, overlayImage );
}
}


I call it with this in my main class:


itemView = [[ItemView alloc] initWithItemUnderlay:defaultItemUnderlay
frame:CGRectMake( ITEM_VIEW_X, ITEM_VIEW_Y, ITEM_VIEW_WIDTH, ITEM_VIEW_HEIGHT )];
[itemView setOverlayImage:defaultOverlayImage];
[customTableView addSubview:itemView];


This gives me the default images. However, if I try and change the top image (overlayImage) using this code:


[itemView setOverlayImage:[item image]];
[itemView drawRect:CGRectMake( ITEM_VIEW_X, ITEM_VIEW_Y, ITEM_VIEW_WIDTH, ITEM_VIEW_HEIGHT )];


It doesn't change the UIView at all... I also get this error message in the console:


<Error>: CGContextDrawImage: invalid context


If anyone knows how I can re-draw my overlayImage after I have set the default underlay/overlay images I would appreciate the help...

Catfish_Man
Apr 23, 2008, 11:33 AM
Manually calling drawRect is basically always a mistake in Cocoa. Use setNeedsDisplayInRect instead.

RossOliver
Apr 23, 2008, 05:47 PM
Manually calling drawRect is basically always a mistake in Cocoa. Use setNeedsDisplayInRect instead.

Ah right, I changed that and it actually crashes now instead of just not working (which is a step forward I guess...).

I think the problem might be because I am getting warnings about my UIView which has my drawRect in not responding to a setOverlayImage message:


warning: 'UIView' may not respond to 'setOverlayInage'


It must work at least once, however, since that is how the default image is set initially...

I don't know why it's complaining - I have declared setOverlayImage like so:


@private
CGImageRef overlayImage;

...

@property( nonatomic, assign ) CGImageRef overlayImage;

...

@synthesize overlayImage;


Any ideas?

Thanks

Sayer
Apr 24, 2008, 10:04 AM
Does the error really say "setOverlayInage" or did you type it in by hand? If its just a typo in your post and not code, then never mind.

Also. In the first bit of code you have "overlayImage = NO" and also have "CGImageRef overlayImage" in the last bit of sample code, which seems like a conflict of types to me.

RossOliver
Apr 24, 2008, 11:38 AM
Does the error really say "setOverlayInage" or did you type it in by hand? If its just a typo in your post and not code, then never mind.

Also. In the first bit of code you have "overlayImage = NO" and also have "CGImageRef overlayImage" in the last bit of sample code, which seems like a conflict of types to me.


Ah, I just mistyped that...

What does the NO constant actually point to? I thought it was like nil and could be applied to any object?