Adding a reflection to an NSImage

To add an reflection in Cocoa to a NSImage object you can use the following NSImage category:

@interface NSImage(MKAddReflection)
- (NSImage*) addReflection:(CGFloat)percentage;
@end

@implementation NSImage(MKAddReflection)

- (NSImage*) addReflection:(CGFloat)percentage
{
	NSAssert(percentage > 0 && percentage <= 1.0, @"Please use percentage between 0 and 1");
	CGRect offscreenFrame = CGRectMake(0, 0, self.size.width, self.size.height*(1.0+percentage));
	NSBitmapImageRep * offscreen = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
														pixelsWide:offscreenFrame.size.width
														pixelsHigh:offscreenFrame.size.height
													 bitsPerSample:8
												   samplesPerPixel:4 
														  hasAlpha:YES
														  isPlanar:NO 
													colorSpaceName:NSDeviceRGBColorSpace
													  bitmapFormat:0
													   bytesPerRow:offscreenFrame.size.width * 4
													  bitsPerPixel:32];
	
	[NSGraphicsContext saveGraphicsState];
	[NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:offscreen]];
	
	[[NSColor clearColor] set];
	NSRectFill(offscreenFrame);
	
	NSGradient * fade = [[NSGradient alloc] initWithStartingColor:[NSColor colorWithCalibratedWhite:1.0 alpha:0.2] endingColor:[NSColor clearColor]];
	CGRect fadeFrame = CGRectMake(0, 0, self.size.width, offscreen.size.height - self.size.height);
	[fade drawInRect:fadeFrame angle:270.0];	
	
    NSAffineTransform* transform = [NSAffineTransform transform];
    [transform translateXBy:0.0 yBy:fadeFrame.size.height];
    [transform scaleXBy:1.0 yBy:-1.0];
    [transform concat];
	
	// Draw the image over the gradient -> becomes reflection
	[self drawAtPoint:NSMakePoint(0, 0) fromRect:CGRectMake(0, 0, self.size.width, self.size.height) operation:NSCompositeSourceIn fraction:1.0];
	
	[transform invert];
	[transform concat];

	// Draw the original image
	[self drawAtPoint:CGPointMake(0, offscreenFrame.size.height - self.size.height) fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
	
	[NSGraphicsContext restoreGraphicsState];
	
	NSImage * imageWithReflection = [[NSImage alloc] initWithSize:offscreenFrame.size];
	[imageWithReflection addRepresentation:offscreen];
	
	return imageWithReflection;
}

To get a copy of a NSImage with a reflection applied you call [image addReflection:0.3], where the float value defines the percentage of the reflection regarding the height of the input image, e.g.

NSImage * input = [[NSImage alloc] initWithContentsOfFile:@"/Users/mk/Desktop/input.jpg"];
NSImage * output = [input addReflection:0.4];

About these ads

One thought on “Adding a reflection to an NSImage

  1. Pingback: NSImage and Reflections

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s