iOS APP界面黑白化处理(灰度处理)(为悼念日准备)(强烈呼吁摒弃百度搜索,推荐google、必应)

  • 2020年初,新冠病毒悄然来袭,上万的民众深受其害,不幸者丧失生命达三千余人,还好政府及时组织医疗团队、制定防护相关措施于四月初得以控制,并在2020年4月4日举国哀悼,哀悼逝去英雄!互联网各大网站、app界面全部变成黑白色以示哀悼。
    网页端、安卓端的同学很快完成相关实现,只剩下iOS端干瞪眼,拜读了鸿洋大神的博客,了解安卓和网页的实现过程。尝试在iOS端尝试却未能成功。但是iPhone手机-->设置-->辅助功能-->显示与文字大小--> 色彩滤镜--> 灰度功能打开,整个手机都黑化了,但这总不能告诉用户打开吧,尴尬。

*最后绞尽脑汁,经高人指点:既然无法像安卓、网页大神那样“一行代码实现黑白化”,那就分步实施吧。于是我们分了三步走:

  1. 图片二值化处理
  2. color
  3. H5页面

*知识点:

  1. 颜色空间,苹果默认使用RGB
  2. RGB灰度处理算法
1. 图片的二值化处理

*图片的二值化处理,百度一下很多,这里我们使用的是bitmap,将每一个色值取出根据灰度算法计算后改变原来的色值。优点是生成的图片不会出现锯齿,模糊现象。核心代码:

- (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;
}
2. 颜色color
  • 我们想所有的控件不管是背景色、边框颜色、文字颜色等,最终都会调用UIColor中的一个API:
+ (UIColor *)colorWithRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha;

*因此我们只需运用runtime进行方法交换,之后在交换的方法中将RGB进行灰度算法处理,alpha跟随设置不做处理。得到的color也就变成了对应的灰度,将color赋值后确实有很大惊喜,全量设置颜色的控件都实现了灰度化。核心代码如下:

+ (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;
}
3. H5页面

*H5页面相对比较简单,至少从前端同事得到帮助。帮助书写了js代码,验证有效后,便是iOS端寻找注入时机。由于项目中WK和UIWeb并存,所有都要做处理。首先是UIWebView的注入,我们尝试在delegate的didFinishNavigation方法中注入,测试发现为时晚矣,界面加载出来后,显示的是正常颜色,然后再变成灰色,显然这是注入晚了。于是查看UIwebview的所有API,寻找注入时机。最后我们发现:

-(void)webView:(id)arg1 resource:(id)arg2 didFinishLoadingFromDataSource:(id)arg3 ;
  • 因此又一次使用了runtime方法交换,拦截到上面API时,在其中注入js代码,完美的解决了闪一下变灰的问题,具体代码如下:
-(void)swizzled_webView:(id)arg1 resource:(id)arg2 didFinishLoadingFromDataSource:(id)arg3 {
    [self grayWebaction:arg1];
    [self swizzled_webView:arg1 resource:arg2 didFinishLoadingFromDataSource:arg3];
}

-(void)grayWebaction:(UIWebView *)web {
    NSString *params = @"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%)';";
    [web stringByEvaluatingJavaScriptFromString:params];
}

*至于WKWebview,不同于UIWebview,可以在初始化时直接注入js代码,便能实现其效果,当然也是通过方法交换,趁此档口注入js,具体代码如下:

- (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;
}
以上便是三步走的过程,也是摸着石头过河,不知道有没有更好地方法,万望大神指教。上面代码文件下载位置,提取码: 7nhg,代码中只是做了灰度效果实现,至于添加标志位判断是否要灰度处理,自己添加。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260