如何在没有混合图层的情况下获得具有渐变的图像?
How can I get a image with gradient without blended layer?
在我的 UITableViewCell 中有一个背景 UIImageView。如果我使用从服务器下载的原始图像,则该 ImageView 上不会显示任何混合层。但是如果我给下载的图像添加渐变(有些图像包含很多白色 space 这使得前面的标签很难看清,所以我必须使图像更暗),混合层显示。如何在避免混合层的情况下向图像添加渐变?
生成渐变图像的代码如下:
- (UIImage *)gs_imageWithDownsideShadow {
return [self gs_imageWithShadow:@[[UIColor gs_colorWithSameRGB:0 alpha:0.3], [UIColor gs_colorWithSameRGB:0 alpha:0.5]]];
}
- (UIImage *)gs_imageWithShadow:(NSArray *)colors
{
CGSize size = self.size;
CGRect rect = CGRectMake(0, 0, size.width, size.height);
UIGraphicsBeginImageContextWithOptions(size, NO, UIScreen.mainScreen.scale);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, 0, self.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextDrawImage(context, rect, self.CGImage);
CGFloat locations[] = {0.0, 1.0};
NSMutableArray *colorRefs = [[NSMutableArray alloc] init];
for (UIColor *color in colors) {
[colorRefs addObject:(__bridge id)color.CGColor];
}
CGColorSpaceRef baseSpace = CGColorSpaceCreateDeviceRGB();
CGGradientRef gradient = CGGradientCreateWithColors(baseSpace, (__bridge CFArrayRef)colorRefs, locations);
CGPoint startPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect));
CGPoint endPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect));
CGContextSaveGState(context);
CGContextAddRect(context, rect);
CGContextClip(context);
CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);
CGContextRestoreGState(context);
CGGradientRelease(gradient);
CGColorSpaceRelease(baseSpace);
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
其 contents
是具有 alpha 通道的图像的图层必须始终与其后面的图层混合。 (iOS 假定图像具有透明度,如果它有 alpha 通道;它不检查是否有任何 alpha 小于 1.0。)
您正在创建带有 alpha 通道的渐变图像,因为您将 NO
传递给 UIGraphicsBeginImageContextWithOptions
的 opaque
参数。
假设所有源图像实际上都是不透明的,您可以(并且应该)通过传递 YES
:
创建不透明的渐变图像
UIGraphicsBeginImageContextWithOptions(size, YES, UIScreen.mainScreen.scale);
传递 YES
告诉 UIKit 创建一个图形上下文,并最终创建一个没有 alpha 通道的图像。
在我的 UITableViewCell 中有一个背景 UIImageView。如果我使用从服务器下载的原始图像,则该 ImageView 上不会显示任何混合层。但是如果我给下载的图像添加渐变(有些图像包含很多白色 space 这使得前面的标签很难看清,所以我必须使图像更暗),混合层显示。如何在避免混合层的情况下向图像添加渐变?
生成渐变图像的代码如下:
- (UIImage *)gs_imageWithDownsideShadow {
return [self gs_imageWithShadow:@[[UIColor gs_colorWithSameRGB:0 alpha:0.3], [UIColor gs_colorWithSameRGB:0 alpha:0.5]]];
}
- (UIImage *)gs_imageWithShadow:(NSArray *)colors
{
CGSize size = self.size;
CGRect rect = CGRectMake(0, 0, size.width, size.height);
UIGraphicsBeginImageContextWithOptions(size, NO, UIScreen.mainScreen.scale);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, 0, self.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextDrawImage(context, rect, self.CGImage);
CGFloat locations[] = {0.0, 1.0};
NSMutableArray *colorRefs = [[NSMutableArray alloc] init];
for (UIColor *color in colors) {
[colorRefs addObject:(__bridge id)color.CGColor];
}
CGColorSpaceRef baseSpace = CGColorSpaceCreateDeviceRGB();
CGGradientRef gradient = CGGradientCreateWithColors(baseSpace, (__bridge CFArrayRef)colorRefs, locations);
CGPoint startPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect));
CGPoint endPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect));
CGContextSaveGState(context);
CGContextAddRect(context, rect);
CGContextClip(context);
CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);
CGContextRestoreGState(context);
CGGradientRelease(gradient);
CGColorSpaceRelease(baseSpace);
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
其 contents
是具有 alpha 通道的图像的图层必须始终与其后面的图层混合。 (iOS 假定图像具有透明度,如果它有 alpha 通道;它不检查是否有任何 alpha 小于 1.0。)
您正在创建带有 alpha 通道的渐变图像,因为您将 NO
传递给 UIGraphicsBeginImageContextWithOptions
的 opaque
参数。
假设所有源图像实际上都是不透明的,您可以(并且应该)通过传递 YES
:
UIGraphicsBeginImageContextWithOptions(size, YES, UIScreen.mainScreen.scale);
传递 YES
告诉 UIKit 创建一个图形上下文,并最终创建一个没有 alpha 通道的图像。