多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

LEColorPicker核心源码拆解:OpenGL ES 2.0如何用Alpha通道给像素投票

LEColorPicker核心源码拆解:OpenGL ES 2.0如何用Alpha通道给像素投票 LEColorPicker核心源码拆解OpenGL ES 2.0如何用Alpha通道给像素投票【免费下载链接】LEColorPickerA Cocoa-Touch system for iOS to get a color scheme in function of an image, like iTunes 11 does.项目地址: https://gitcode.com/gh_mirrors/le/LEColorPicker你是否好奇过iTunes 11 这类应用是如何从一张专辑封面里自动匹配出文字与背景颜色的iOS 开源项目LEColorPicker做的就是这件事给它一张图片它自动提取出一套三色配色方案背景色 主文字色 次文字色。这篇文章拆解它的核心源码重点讲清楚它如何借助 OpenGL ES 2.0 的片元着色器让每个像素用Alpha 通道并行投票选出整张图的主导色——这也是这个库最巧妙的部分。一、先看效果3行代码提取图片配色方案LEColorPicker 的使用非常简单创建一个实例调用colorSchemeFromImage:传入一张 UIImage就会得到一个 LEColorScheme 对象里面有三个现成的 UIColor 属性LEColorPicker *colorPicker [[LEColorPicker alloc] init]; LEColorScheme *colorScheme [colorPicker colorSchemeFromImage:image]; aView.backgroundColor [colorScheme backgroundColor]; // 背景色 titleTextField.textColor [colorScheme primaryTextColor]; // 主文字色示例输入图和提取效果对比演示工程里只需在 ViewController.m 的configureOutPutView:中把三个颜色赋给视图滑到下一张图时配色就会自动切换。二、处理流水线4步从任意图片到3种颜色整个提取流程可以概括为 4 步入口方法见 colorSchemeFromImage:步骤做什么关键点1️⃣ 缩小图片把原图缩放到固定 32×32尺寸恒定计算量骤降2️⃣ 初始化 GPU创建 OpenGL ES 2.0 上下文、帧缓冲见 setupOpenGL3️⃣ 着色器投票片元着色器统计每个颜色的得票数核心魔法下文详解4️⃣ CPU 读回找出 Alpha 最大的像素做对比度校验输出三色方案为什么要先缩到 32×32因为选主导色不需要照片级精度1024 个像素足以代表整张图的色彩分布还能保证纹理是正方形后续计算全部固定化。三、核心技巧拆解片元着色器如何给像素投票这是整个项目最精华的设计源码位于 LEColorPicker.m 的片元着色器。用大白话讲GPU 会同时为输出的 1024 个像素各执行一次着色器程序这就是并行每个像素先把自己的颜色转换成YUV 色彩空间Y 表示亮度U/V 表示色调而不是直接用 RGB——这样比较颜色更符合人眼的感知然后它遍历左上角 16×16 区域内的全部256 个像素逐个与自己的 YUV 距离做比较只要距离小于 0.1也就是长得差不多就给自己记一票accumulator 0.0039投票结束输出结果RGB 是它原本的颜色Alpha 是它的得票总数。if (d 0.1) { accumulator accumulator 0.0039; // 投一票 } ... gl_FragColor vec4(r, g, b, accumulator); // A通道 得票数这里有个隐藏的细节0.0039 × 256 ≈ 1.0。也就是说如果某个颜色恰好被 256 个像素全票支持Alpha 会刚好满值255支持它的像素越多Alpha 越接近 255。Alpha 通道就这样从透明度变成了得票率——这就是标题所说的用 Alpha 通道给像素投票。四、CPU读回如何从投票结果中找出赢家GPU 画完 32×32 的投票图后CPU 用glReadPixels把结果读回内存然后做三轮筛选背景色遍历所有像素取 Alpha 最大的那个RGB 就是主导色colorWithBiggerCountFromImageWidth:主文字色排除与背景色太近的像素容差 0.5再取 Alpha 最大者次文字色同时排除背景色和主文字色容差 0.3再取 Alpha 最大者。这三轮逻辑都在 findTextColorsTaskForColorScheme: 中。最后还有一道兜底用 UIColorYUVSpace 计算的亮度差若不足 125、或色差不足 500说明次文字色和背景对比不够会直接退化为纯黑或纯白保证文字永远读得清。五、为什么用GPUOpenGL ES 2.0 的性能账本用纯 CPU 方案统计颜色最朴素的做法是逐像素两两比较百万像素的照片意味着天文数字次运算。而 LEColorPicker 的思路是先缩到 32×32把问题规模压到 1024 个像素交给 GPU 后1024 个片元着色器并行执行每个做 256 次纹理采样——这种大量并行采样正是 GPU 的强项整个任务运行在低优先级的串行队列上且监听应用前后台切换退到后台立即dispatch_suspend挂起任务源码省电又省心。这也是官方说明真机上比模拟器更快的原因——真机有完整的图形硬件在并行干活。六、动手跑起来最快体验LEColorPicker的步骤获取代码git clone https://gitcode.com/gh_mirrors/le/LEColorPicker在你的 Xcode 工程中添加OpenGLES框架打开LEColorPickerDemo.xcodeproj直接运行 Demo想测自己的图把 PNG 丢进 Resources/ 文件夹即可不要带 Default 前缀。效果示例一张红色为主的飞机漩涡图自动得到红色背景 白色文字七、总结可以调一调的关键参数读懂源码后你会发现整套投票系统由几个很直观的旋钮控制32缩小后的边长决定纹理大小与并行规模0.1YUV 距离阈值决定多像才算一票0.0039每票的权重256 票刚好满格 Alpha0.5 / 0.3文字色与背景色、主文字色的去重容差。这套着色器投票 Alpha 计票 CPU 读回的模式本质上是把一次遍历统计搬上了并行硬件思路完全可以迁移到其他需要统计图像分布的场景值得收藏进你的 iOS 工具库。【免费下载链接】LEColorPickerA Cocoa-Touch system for iOS to get a color scheme in function of an image, like iTunes 11 does.项目地址: https://gitcode.com/gh_mirrors/le/LEColorPicker创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表