iOS本身在设置里面是有色盲模式的,打开后效果极佳,可以说是最好的灰度处理了。但是苹果平没有放开这个API,我们也无法要求用户在特定时间打开它。
而且这个功能是把整个手机都置灰了。iOS APP界面的灰度处理不能像web和安卓那样简单,但是也有方法。
这里根据网络资料整理的两种方案。我们项目目前就是这两种方案混合使用的。
方案一
最开始就想的就是能不能想web那样一键处理,或者增加一个滤镜什么的,简单便捷,不需要处理一个个控件。
将App所有的视图通过滤镜,都变为灰色,也就是在window或者首页的view上添加这样一种灰色滤镜效果,使得整个App界面或者首页变为灰色
+ (void)addGreyFilterToView:(UIView *)view {
UIView *greyView = [[UIView alloc] initWithFrame:view.bounds];
greyView.userInteractionEnabled = NO;
greyView.tag = kFJFGreyFilterTag;
greyView.backgroundColor = [UIColor lightGrayColor];
greyView.layer.compositingFilter = @"saturationBlendMode";
greyView.layer.zPosition = FLT_MAX;
[view addSubview:greyView];
}
+ (void)removeGreyFilterToView:(UIView *)view {
UIView *greyView = [view viewWithTag:kFJFGreyFilterTag];
[greyView removeFromSuperview];
}
该方法的主要原理是设置一个浅灰色的lightGrayColor的颜色,然后将该浅灰色的饱和度,应用到将要显示的视图上,使得将要显示的视图,显示灰色。
饱和度是指色彩的鲜艳程度,也称色彩的纯度。饱和度取决于该色中含色成分和消色成分(灰色)的比例。含色成分越大,饱和度越大;消色成分越大,饱和度越小。
最新实测:iOS12.4;12.5会出现bug。
方案二
对UIColor、UIImage、UIImageView、WKWebView等进行各个处理.
- 图片二值化处理
- color
- H5页面
- 图片处理
- (UIImage *)grayImage {
const int RED =1;
const int GREEN =2;
const int BLUE =3;
// Create image rectangle with current image width/height
CGRect imageRect = CGRectMake(0,0, self.size.width* self.scale, self.size.height* self.scale);
int width = imageRect.size.width;
int height = imageRect.size.height;
// the pixels will be painted to this array
uint32_t *pixels = (uint32_t*) malloc(width * height *sizeof(uint32_t));
// clear the pixels so any transparency is preserved
memset(pixels,0, width * height *sizeof(uint32_t));
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
// create a context with RGBA pixels
CGContextRef context = CGBitmapContextCreate(pixels, width, height,8, width *sizeof(uint32_t), colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedLast);
// paint the bitmap to our context which will fill in the pixels array
CGContextDrawImage(context,CGRectMake(0,0, width, height), [self CGImage]);
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
uint8_t *rgbaPixel = (uint8_t*) &pixels[y * width + x];
// convert to grayscale using recommended method: http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale
uint32_t gray = 0.3 * rgbaPixel[RED] +0.59 * rgbaPixel[GREEN] +0.11 * rgbaPixel[BLUE];
// set the pixels to gray
rgbaPixel[RED] = gray;
rgbaPixel[GREEN] = gray;
rgbaPixel[BLUE] = gray;
}
}
// create a new CGImageRef from our context with the modified pixels
CGImageRef imageRef = CGBitmapContextCreateImage(context);
// we're done with the context, color space, and pixels
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
free(pixels);
// make a new UIImage to return
UIImage *resultUIImage = [UIImage imageWithCGImage:imageRef scale:self.scale orientation:UIImageOrientationUp];
// we're done with image now too
CGImageRelease(imageRef);
return resultUIImage;
}
public func grayImage() -> UIImage? {
// 获得宽度和高度数值
let width = Int(size.width)
let height = Int(size.height)
// 创建灰度色彩空间对象,各种设备对待颜色的方式都不一样,颜色必须有一个相关的色彩空间
let spaceRef = CGColorSpaceCreateDeviceGray()
// 参数data指向渲染的绘制内存的地址,bitsOerComponent表示内存中像素的每个组件的位数,bytesPerRow表示每一行在内存中占的比特数,space表示使用的颜色空间,bitmapInfo表示是否包含alpha通道
// CGBitmapInfo().rawValue
guard let context = CGContext(data: nil, width: width, height: height, bitsPerComponent: 8, bytesPerRow: 0, space: spaceRef, bitmapInfo: CGBitmapInfo().rawValue) else {
return nil
}
// 然后创建一个和原视图同样尺寸的空间
let rect = CGRect(x: 0, y: 0, width: width, height: height)
// 在灰度上下文中画入图片
// context.alpha
guard let cgImage = cgImage else {
return nil
}
context.draw(cgImage, in: rect)
// 从上下文中获取并生成专为灰度的图片
if let cgImage = context.makeImage() {
let grayImage = UIImage.init(cgImage: cgImage)
return grayImage
}
return nil
}
- 色值处理
+ (UIColor *)changeGrayWithColor:(UIColor *)color Red:(CGFloat)r green:(CGFloat)g blue:(CGFloat)b alpha:(CGFloat)a {
CGFloat gray = r * 0.299 +g * 0.587 + b * 0.114;
UIColor *grayColor = [UIColor colorWithWhite:gray alpha:a];
return grayColor;
}
- H5
- (instancetype)lg_initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration {
// js脚本
NSString *jScript = @"var filter = '-webkit-filter:grayscale(100%);-moz-filter:grayscale(100%); -ms-filter:grayscale(100%); -o-filter:grayscale(100%) filter:grayscale(100%);';document.getElementsByTagName('html')[0].style.filter = 'grayscale(100%)';";
// 注入
WKUserScript *wkUScript = [[WKUserScript alloc] initWithSource:jScript injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];
WKUserContentController *wkUController = [[WKUserContentController alloc] init];
[wkUController addUserScript:wkUScript];
// 配置对象
WKWebViewConfiguration *wkWebConfig = [[WKWebViewConfiguration alloc] init];
wkWebConfig.userContentController = wkUController;
configuration = wkWebConfig;
WKWebView *webView = [self lg_initWithFrame:frame configuration:configuration];
return webView;
}
然后对各个控件赋值取值的地方,添加一个控制开关,每次启动的时候,通过这个开关开控制方法。
也可以通过黑魔法交换方法。将原来的赋值方法替换为我们需要的结果方法。
ps: xib需要特殊处理。
网络转发总结,参考文章如下: