Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Coverflow: Modified reflection for coverflow #194

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 5 additions & 4 deletions src/TapkuLibrary/TKCoverflowCoverView.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,6 @@
/** The coverflow image. */
@property (strong,nonatomic) UIImage *image;

/** The gradient layer the will create the reflection below the coverflow image */
@property (strong,nonatomic) CAGradientLayer *gradientLayer;

/** The height of the image. This property will help coverflow adjust views to display images with different heights. */
@property (assign,nonatomic) CGFloat baseline; // set this property for displaying images w/ different heights

Expand All @@ -54,5 +51,9 @@

@property (nonatomic,strong) UIImageView *reflected;

@property (assign,nonatomic) BOOL showReflection;
- (UIImage *)reflectedImage:(UIImageView *)fromImage withHeight:(NSUInteger)height;
CGImageRef CreateGradientImage(int pixelsWide, int pixelsHigh);
CGContextRef MyCreateBitmapContext(int pixelsWide, int pixelsHigh);

@end
@end
142 changes: 110 additions & 32 deletions src/TapkuLibrary/TKCoverflowCoverView.m
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,12 @@

@implementation TKCoverflowCoverView

static const CGFloat kDefaultReflectionFraction = 0.35;
static const CGFloat kDefaultReflectionOpacity = 0.40;

- (id) initWithFrame:(CGRect)frame showReflection:(BOOL)reflection{
if(!(self=[super initWithFrame:frame])) return nil;

self.showReflection = reflection;

self.opaque = NO;
self.backgroundColor = [UIColor clearColor];
Expand All @@ -46,48 +49,28 @@ - (id) initWithFrame:(CGRect)frame showReflection:(BOOL)reflection{
self.imageView = [[UIImageView alloc] initWithFrame:self.bounds];
[self addSubview:self.imageView];

if(reflection){

CGRect reflectRect = CGRectMakeWithSize(0, self.frame.size.height, self.bounds.size);

self.reflected = [[UIImageView alloc] initWithFrame:reflectRect];
self.reflected.transform = CGAffineTransformScale(self.reflected.transform, 1, -1);
[self addSubview:self.reflected];

self.gradientLayer = [CAGradientLayer layer];
self.gradientLayer.colors = [NSArray arrayWithObjects:(id)[UIColor colorWithWhite:0 alpha:0.5].CGColor,(id)[UIColor colorWithWhite:0 alpha:1].CGColor,nil];
self.gradientLayer.startPoint = CGPointMake(0,0);
self.gradientLayer.endPoint = CGPointMake(0,0.3);
self.gradientLayer.frame = reflectRect;
[self.layer addSublayer:self.gradientLayer];
}

return self;
}

- (id) initWithFrame:(CGRect)frame {
return [self initWithFrame:frame showReflection:YES];
}

- (void) setImage:(UIImage *)img{
[CATransaction begin];
[CATransaction setAnimationDuration:0.0f];

if(img==nil){
[CATransaction begin];
[CATransaction setAnimationDuration:0.0f];
self.imageView.frame = self.bounds;

if(self.gradientLayer){
self.reflected.image = nil;
self.gradientLayer.frame = self.reflected.frame = CGRectMakeWithSize(0,self.frame.size.height,self.bounds.size);
if(self.showReflection){
self.reflected = nil;
}
self.imageView.image = nil;
[CATransaction commit];
return;
}


[CATransaction begin];
[CATransaction setAnimationDuration:0.0f];


UIImage *image = img;
CGFloat w = image.size.width;
CGFloat h = image.size.height;
Expand All @@ -99,18 +82,113 @@ - (void) setImage:(UIImage *)img{
self.imageView.frame = CGRectMake(0, y, w, h);
self.imageView.image = image;

if(self.gradientLayer){
self.reflected.frame = self.gradientLayer.frame = CGRectMake(0, y + h, w, h);
self.reflected.image = image;
if(self.showReflection){
NSUInteger reflectionHeight = self.imageView.bounds.size.height * kDefaultReflectionFraction;
CGRect reflectRect = CGRectMake(0, y+h, self.imageView.bounds.size.width,reflectionHeight);
self.reflected = [[UIImageView alloc] initWithFrame:reflectRect];
self.reflected.image = [self reflectedImage:self.imageView withHeight:reflectionHeight];
self.reflected.alpha = kDefaultReflectionOpacity;
[self addSubview:self.reflected];
}

[CATransaction commit];


}

- (UIImage*) image{
return self.imageView.image;
}

#pragma mark - Image Reflection

CGImageRef CreateGradientImage(int pixelsWide, int pixelsHigh)
{
CGImageRef theCGImage = NULL;

// gradient is always black-white and the mask must be in the gray colorspace
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();

// create the bitmap context
CGContextRef gradientBitmapContext = CGBitmapContextCreate(NULL, pixelsWide, pixelsHigh,
8, 0, colorSpace, kCGImageAlphaNone);

// define the start and end grayscale values (with the alpha, even though
// our bitmap context doesn't support alpha the gradient requires it)
CGFloat colors[] = {0.0, 1.0, 1.0, 1.0};

// create the CGGradient and then release the gray color space
CGGradientRef grayScaleGradient = CGGradientCreateWithColorComponents(colorSpace, colors, NULL, 2);
CGColorSpaceRelease(colorSpace);

// create the start and end points for the gradient vector (straight down)
CGPoint gradientStartPoint = CGPointZero;
CGPoint gradientEndPoint = CGPointMake(0, pixelsHigh);

// draw the gradient into the gray bitmap context
CGContextDrawLinearGradient(gradientBitmapContext, grayScaleGradient, gradientStartPoint,
gradientEndPoint, kCGGradientDrawsAfterEndLocation);
CGGradientRelease(grayScaleGradient);

// convert the context into a CGImageRef and release the context
theCGImage = CGBitmapContextCreateImage(gradientBitmapContext);
CGContextRelease(gradientBitmapContext);

// return the imageref containing the gradient
return theCGImage;
}

CGContextRef MyCreateBitmapContext(int pixelsWide, int pixelsHigh)
{
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

// create the bitmap context
CGContextRef bitmapContext = CGBitmapContextCreate (NULL, pixelsWide, pixelsHigh, 8,
0, colorSpace,
// this will give us an optimal BGRA format for the device:
(kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst));
CGColorSpaceRelease(colorSpace);

return bitmapContext;
}

- (UIImage *)reflectedImage:(UIImageView *)fromImage withHeight:(NSUInteger)height
{
if(height == 0)
return nil;

// create a bitmap graphics context the size of the image
CGContextRef mainViewContentContext = MyCreateBitmapContext(fromImage.bounds.size.width, height);

// create a 2 bit CGImage containing a gradient that will be used for masking the
// main view content to create the 'fade' of the reflection. The CGImageCreateWithMask
// function will stretch the bitmap image as required, so we can create a 1 pixel wide gradient
CGImageRef gradientMaskImage = CreateGradientImage(1, height);

// create an image by masking the bitmap of the mainView content with the gradient view
// then release the pre-masked content bitmap and the gradient bitmap
CGContextClipToMask(mainViewContentContext, CGRectMake(0.0, 0.0, fromImage.bounds.size.width, height), gradientMaskImage);
CGImageRelease(gradientMaskImage);

// In order to grab the part of the image that we want to render, we move the context origin to the
// height of the image that we want to capture, then we flip the context so that the image draws upside down.
CGContextTranslateCTM(mainViewContentContext, 0.0, height);
CGContextScaleCTM(mainViewContentContext, 1.0, -1.0);

// draw the image into the bitmap context
CGContextDrawImage(mainViewContentContext, fromImage.bounds, fromImage.image.CGImage);

// create CGImageRef of the main view bitmap content, and then release that bitmap context
CGImageRef reflectionImage = CGBitmapContextCreateImage(mainViewContentContext);
CGContextRelease(mainViewContentContext);

// convert the finished reflection image to a UIImage
UIImage *theImage = [UIImage imageWithCGImage:reflectionImage];

// image is retained by the property setting above, so we can release the original
CGImageRelease(reflectionImage);

return theImage;
}



@end