FXBlurView
FXBlurView copied to clipboard
Feature: Font Color For Rect
I have quite a few FXBlurViews with labels on them and with the content behind them changing from a bright color to a dull color (UIImageViews to be exact). I'd really like to be able to pass the FXBlurView the NSRect for the UILabels frame and have it return the best color for the label to make it readable. Even if it just returned white or black for the moment as a proof of concept.
I hope something like this can be implemented.
That does sound pretty neat. It's a little bit out if scope for what I'm trying to do with FXBlurview, but I'll think about it.
Thanks Nick. Would be fantastic. I might take a look at it and see if I can come up with anything. Let me know if you work something out first.
Fantastic job by the way, performance is fantastic compared to a few other solutions I have looked at.
I've come up with the following solution. It works and doesn't appear to impact overall performance since it's only rendering the required number of pixels to get the color average for the specified rect.
Please let me know what you think.
@implementation UIView (FXBlurView)
- (UIColor *) colorAverageForRect:(CGRect)rect
{
int red = 0;
int green = 0;
int blue = 0;
int count = 0;
int width = rect.size.width;
int height = rect.size.height;
int bitsPerComponent = 8;
int bytesPerRow = 4 * width;
unsigned char pixels[bytesPerRow*height];
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(pixels, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGContextTranslateCTM(context, -rect.origin.x, -rect.origin.y);
[self.layer renderInContext:context];
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
int pixel_y = y*(bytesPerRow);
int pixel_x = x*4;
red += pixels[ pixel_y + pixel_x ];
green += pixels[ pixel_y + pixel_x + 1];
blue += pixels[ pixel_y + pixel_x + 2];
count++;
}
}
red /= count;
green /= count;
blue /= count;
return [UIColor colorWithRed:red/255.0f green:green/255.0f blue:blue/255.0f alpha:1.0f];
}
- (UIColor *) contrastingTextColorForRect:(CGRect)rect
{
UIColor *averageBackColor = [self colorAverageForRect:rect];
const CGFloat *componentColors = CGColorGetComponents(averageBackColor.CGColor);
CGFloat colorBrightness = ((componentColors[0] * 299) +
(componentColors[1] * 587) +
(componentColors[2] * 114)) / 1000;
if (colorBrightness < 0.5)
{
return [UIColor whiteColor];
}
else
{
return [UIColor blackColor];
}
}
@end
Or a colored version:
- (UIColor *) contrastingTextColorForRect:(CGRect)rect
{
UIColor *averageBackColor = [self colorAverageForRect:rect];
CGColorRef oldCGColor = averageBackColor.CGColor;
size_t numberOfComponents = CGColorGetNumberOfComponents(oldCGColor);
// can not invert - the only component is the alpha
// e.g. self == [UIColor groupTableViewBackgroundColor]
if (numberOfComponents == 1) {
return [UIColor colorWithCGColor:oldCGColor];
}
const CGFloat *oldComponentColors = CGColorGetComponents(oldCGColor);
CGFloat newComponentColors[numberOfComponents];
int i = (int)numberOfComponents - 1;
newComponentColors[i] = oldComponentColors[i]; // alpha
while (--i >= 0) {
newComponentColors[i] = 1 - oldComponentColors[i];
}
CGColorRef newCGColor = CGColorCreate(CGColorGetColorSpace(oldCGColor), newComponentColors);
UIColor *newColor = [UIColor colorWithCGColor:newCGColor];
CGColorRelease(newCGColor);
return newColor;
}