核心内容摘要
玩转欧姆龙CP1H功能块】工控老司机教你“偷懒“秘籍
GPUImageColorBurnBlendFilter 代码全解析本文将全面解析GPUImageColorBurnBlendFilter.java代码逐行添加注释并分段讲解代码含义、核心原理同时给出实际使用示例。
该代码是基于 Android 平台 GPUImage 框架的颜色加深Color Burn混合滤镜用于将两张图片/纹理按“颜色加深”模式融合底层基于 OpenGL ES 着色器实现高效的 GPU 渲染。
完整带注释的代码/* * Copyright (C) 2018 CyberAgent, Inc. * 版权声明代码版权归属 CyberAgent, Inc.日本赛博特工公司2018年 *//* * Licensed under the Apache License, Version
0 (the License); * 许可证声明代码遵循 Apache License
0 开源协议 *//* * you may not use this file except in compliance with the License. * 使用约束必须遵守许可证条款才能使用此文件 *//* * You may obtain a copy of the License at * 许可证获取地址提示 *//* * http://www.apache.org/licenses/LICENSE-
0 * Apache
0 许可证官方地址 *//* * Unless required by applicable law or agreed to in writing, software * 分发约束除非法律要求或书面协议约定否则软件按“原样”分发 *//* * distributed under the License is distributed on an AS IS BASIS, * 分发基础无任何形式的担保明示/暗示 *//* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 担保声明不附带任何担保或使用条件 *//* * See the License for the specific language governing permissions and * 权限提示许可证中定义了具体的使用权限和限制 *//* * limitations under the License. */// 声明类所属包路径GPUImage 框架的滤镜统一存放包packagejp.co.cyberagent.android.gpuimage.filter;// 定义颜色加深混合滤镜类继承自 GPUImageTwoInputFilter双输入纹理滤镜基类// GPUImageTwoInputFilter 封装了双纹理输入的基础渲染逻辑如纹理绑定、着色器编译等publicclassGPUImageColorBurnBlendFilterextendsGPUImageTwoInputFilter{// 定义颜色加深混合的片段着色器常量核心滤镜逻辑// 片段着色器Fragment Shader运行在 GPU 上负责计算每个像素的最终颜色publicstaticfinalStringCOLOR_BURN_BLEND_FRAGMENT_SHADERvarying highp vec2 textureCoordinate;\n// varying从顶点着色器传递的插值变量highp高精度浮点适配移动端 GPUvec2二维向量存储纹理坐标// textureCoordinate2第二个输入纹理的坐标 varying highp vec2 textureCoordinate2;\n\n// uniform着色器执行期间不变的全局常量sampler2D2D 纹理采样器绑定输入纹理// inputImageTexture第一个输入纹理底层纹理的采样器 uniform sampler2D inputImageTexture;\n// inputImageTexture2第二个输入纹理顶层纹理的采样器 uniform sampler2D inputImageTexture2;\n \n// 片段着色器主函数每个像素都会执行一次 void main()\n {\n// 从第一个纹理采样颜色texture2D(采样器, 纹理坐标) 返回 vec4RGBA取值
0-
0// mediump中精度浮点平衡性能与精度textureColor底层纹理当前像素颜色 mediump vec4 textureColor texture2D(inputImageTexture, textureCoordinate);\n// 从第二个纹理采样颜色textureColor2 为顶层纹理当前像素颜色 mediump vec4 textureColor2 texture2D(inputImageTexture2, textureCoordinate
;\n// 定义白色向量RGBA 均为
0用于颜色加深公式计算 mediump vec4 whiteColor vec4(
1.
;\n// 核心公式颜色加深混合算法// gl_FragColor片段着色器输出变量代表当前像素最终颜色// 公式逻辑白色 - (白色 - 底层颜色) / 顶层颜色 → 让混合后颜色更暗实现“加深”效果 gl_FragColor whiteColor - (whiteColor - textureColor) / textureColor2;\n };// 无参构造函数publicGPUImageColorBurnBlendFilter(){// 调用父类构造函数传入自定义片段着色器// 父类会完成编译顶点着色器基类默认 片段着色器、链接着色器程序、初始化 OpenGL ES 环境super(COLOR_BURN_BLEND_FRAGMENT_SHADER);}}代码分段核心解析
版权与许可声明第
行这是开源项目的标准声明核心作用声明版权归属CyberAgent, Inc.和年份该公司是 GPUImage-Android 框架的核心维护者明确代码遵循 Apache License
0 协议允许商业使用、修改、分发但需保留版权声明且软件“按原样”分发无任何担保。
包声明第 17 行package jp.co.cyberagent.android.gpuimage.filter;GPUImage 框架将所有滤镜类统一放在该包下便于类的管理和外部引用符合 Android 开发的包命名规范。
类定义第 19 行public class GPUImageColorBurnBlendFilter extends GPUImageTwoInputFilter继承关系GPUImageTwoInputFilter是双输入纹理滤镜的基类封装了“绑定两个纹理、传递纹理坐标、编译着色器”等重复逻辑子类只需实现自定义的混合算法命名规范GPUImage 框架的滤镜命名为GPUImage 效果名 BlendFilter混合滤镜语义清晰。
片段着色器常量核心逻辑第
行着色器是 OpenGL ES 实现滤镜的核心该常量定义了“颜色加深”的像素计算规则逐行解析代码片段核心作用varying highp vec2 textureCoordinate接收顶点着色器传递的第一个纹理坐标插值后适配每个像素highp保证坐标精度uniform sampler2D inputImageTexture绑定第一个输入纹理底层图片是读取纹理颜色的“入口”texture2D(inputImageTexture, textureCoordinate)从底层纹理中根据坐标读取像素颜色返回vec4类型RGBA 四个通道取值
0-
0gl_FragColor whiteColor - (whiteColor - textureColor) / textureColor2颜色加深核心公式- 若顶层纹理为白色
1.
0
0 - (
0 - 底层颜色)/
0 底层颜色无变化- 若顶层纹理颜色
0(
0 - 底层颜色)/顶层颜色会放大最终颜色比底层更暗实现“加深”- 注GPUImage 框架会自动处理“顶层颜色为
0 导致除零”的异常。
构造函数第
行publicGPUImageColorBurnBlendFilter(){super(COLOR_BURN_BLEND_FRAGMENT_SHADER);}无参构造函数便于外部创建实例调用父类构造函数传入自定义片段着色器父类会自动完成编译着色器、链接着色器程序、初始化纹理绑定环境子类无需重复实现底层 OpenGL ES 逻辑。
片段着色器代码深度解析这段代码是 OpenGL ES 片段着色器Fragment Shader的核心实现用于在 GPU 上逐像素计算颜色加深Color Burn混合效果是GPUImageColorBurnBlendFilter滤镜的核心逻辑。
以下逐行拆解解析代码逐行注释与含义// 拼接后的完整着色器代码带逐行注释varying highp vec2 textureCoordinate;//
底层纹理坐标变量varying highp vec2 textureCoordinate2;//
顶层混合纹理坐标变量uniform sampler2D inputImageTexture;//
底层纹理采样器uniform sampler2D inputImageTexture2;//
顶层混合纹理采样器voidmain()//
着色器主函数逐像素执行{//
采样底层纹理当前像素的颜色RGBAmediump vec4 textureColortexture2D(inputImageTexture,textureCoordinate);//
采样顶层纹理当前像素的颜色RGBAmediump vec4 textureColor2texture2D(inputImageTexture2,textureCoordinate
;//
定义白色向量RGBA 通道均为
0mediump vec4 whiteColorvec4(
1.
;//
颜色加深核心公式计算最终像素颜色gl_FragColorwhiteColor-(whiteColor-textureColor)/textureColor2;}关键行详细解析
纹理坐标变量第
行varying highp vec2 textureCoordinate; varying highp vec2 textureCoordinate2;varyingOpenGL ES 关键字代表插值变量——该变量的值由顶点着色器Vertex Shader传递并在像素间自动插值比如图片拉伸/缩放时坐标会平滑过渡。
highp精度限定符代表高精度浮点型high precision移动端 GPU 中用于纹理坐标可避免精度丢失坐标偏移、模糊。
vec2二维向量类型存储纹理坐标范围
0~
0(0,
对应纹理左上角(1,
对应右下角。
textureCoordinate底层纹理被混合的基础图片的坐标textureCoordinate2顶层纹理用于混合的叠加图片的坐标。
纹理采样器第
行uniform sampler2D inputImageTexture; uniform sampler2D inputImageTexture2;uniformOpenGL ES 关键字代表全局常量——着色器执行期间值不变由 Java 层GPUImage 框架传入绑定具体的纹理ID。
sampler2D2D 纹理采样器类型是读取纹理像素颜色的“接口”可以理解为“纹理的句柄”。
inputImageTexture绑定底层纹理inputImageTexture2绑定顶层混合纹理。
主函数与像素采样第
行void main() { mediump vec4 textureColor texture2D(inputImageTexture, textureCoordinate); mediump vec4 textureColor2 texture2D(inputImageTexture2, textureCoordinate
; mediump vec4 whiteColor vec4(
1.
; // ... }void main()片段着色器的入口函数每个像素都会执行一次是像素颜色计算的核心入口。
mediump精度限定符代表中精度浮点型medium precision平衡移动端 GPU 的性能与精度颜色计算无需超高精度。
vec4四维向量类型存储像素的 RGBA 颜色值每个通道取值
0~
0比如vec4(
0,
0,
0,
1.
是纯红色。
texture2D(sampler2D sampler, vec2 coord)OpenGL ES 内置函数根据纹理采样器和坐标读取对应位置的像素颜色返回vec4类型的 RGBA 值。
核心混合公式第9行gl_FragColor whiteColor - (whiteColor - textureColor) / textureColor2;gl_FragColorOpenGL ES 内置输出变量代表当前像素的最终颜色赋值后会直接渲染到屏幕/纹理。
公式原理颜色加深算法拆解公式以单个颜色通道为例如 R 通道最终R值
0 - (
0 - 底层R值) / 顶层R值若顶层纹理像素为白色
1.
0
0 - (
0 - 底层R值)/
0 底层R值→ 混合后无变化若顶层纹理像素颜色
0非白色(
0 - 底层R值)/顶层R值会被放大最终 R 值 底层 R 值 → 颜色更暗实现“加深”效果若顶层纹理像素为黑色
0公式会出现除零GPUImage 框架底层会自动处理比如限制最小值避免渲染异常。
颜色加深效果的视觉特征颜色加深混合的核心是让底层颜色变得更暗模拟“用颜料加深底色”的效果顶层纹理越暗通道值越小底层颜色加深越明显顶层纹理为白色时底层颜色完全不变顶层纹理为黑色时底层颜色会被加深为纯黑。
补充
注意事项精度选择纹理坐标用highp避免坐标偏移颜色计算用mediump节省 GPU 算力是移动端 OpenGL ES 的最佳实践除零保护若顶层纹理某通道值为
0公式会触发除零实际开发中可增加边界判断如textureColor2 max(textureColor2,
0.
避免颜色异常通道同步公式会同时作用于 RGBA 四个通道若只需混合 RGB忽略透明度可修改公式为gl_FragColor vec4(whiteColor.rgb - (whiteColor.rgb - textureColor.rgb) / textureColor
rgb, textureColor.a);。
该滤镜的实际
使用方法
前置条件集成 GPUImage 框架在项目build.gradle中添加依赖以
2.
0 版本为例dependencies { implementation jp.co.cyberagent.android:gpuimage:
2.
0 }
布局文件显示滤镜效果在res/layout/activity_main.xml中添加GPUImageViewGPUImage 框架的图片显示控件?xml version
0 encodingutf-8?LinearLayoutxmlns:androidhttp://schemas.android.com/apk/res/androidandroid:layout_widthmatch_parentandroid:layout_heightmatch_parentjp.co.cyberagent.android.gpuimage.GPUImageViewandroid:idid/gpuImageViewandroid:layout_widthmatch_parentandroid:layout_heightmatch_parent//LinearLayout
代码实现加载图片 应用滤镜importandroid.graphics.Bitmap;importandroid.graphics.BitmapFactory;importandroid.os.Bundle;importandroidx.appcompat.app.AppCompatActivity;importjp.co.cyberagent.android.gpuimage.GPUImage;importjp.co.cyberagent.android.gpuimage.GPUImageView;importjp.co.cyberagent.android.gpuimage.filter.GPUImageColorBurnBlendFilter;publicclassMainActivityextendsAppCompatActivity{privateGPUImagemGPUImage;privateGPUImageViewmGPUImageView;OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//
初始化 GPUImage 核心类和显示控件mGPUImageViewfindViewById(R.id.gpuImageView);mGPUImagenewGPUImage(this);mGPUImage.setGLSurfaceView(mGPUImageView);// 绑定显示控件//
加载两张纹理图片底层图 顶层混合图BitmapbaseBitmapBitmapFactory.decodeResource(getResources(),R.drawable.base_img);// 底层图BitmapblendBitmapBitmapFactory.decodeResource(getResources(),R.drawable.blend_img);// 顶层混合图//
创建颜色加深混合滤镜实例GPUImageColorBurnBlendFiltercolorBurnFilternewGPUImageColorBurnBlendFilter();//
设置滤镜双输入滤镜需传入第二个纹理mGPUImage.setFilter(colorBurnFilter);// 设置主滤镜colorBurnFilter.setSecondImage(blendBitmap);// 传入第二个纹理顶层图//
加载底层图并显示滤镜效果mGPUImage.setImage(baseBitmap);}// 可选回收资源避免内存泄漏OverrideprotectedvoidonDestroy(){super.onDestroy();if(mGPUImage!null){mGPUImage.deleteImage();}}}
使用
注意事项纹理尺寸两张图片尺寸建议一致若不一致GPUImage 会自动缩放纹理坐标但可能导致混合效果偏差性能优化着色器中优先使用mediump中精度减少highp以降低 GPU 开销异常处理若顶层纹理颜色为
0需在着色器中增加边界判断如textureColor2 max(textureColor2,
0.
;避免除零错误资源回收使用完Bitmap后及时调用recycle()GPUImage实例在页面销毁时调用deleteImage()释放 OpenGL 资源。
总结GPUImageColorBurnBlendFilter是基于 GPUImage 框架的双输入混合滤镜核心通过 OpenGL ES 片段着色器实现“颜色加深”算法。
其代码结构简洁复用了基类的双纹理渲染逻辑仅需实现自定义的混合公式实际使用时只需集成框架、传入两张纹理即可快速实现颜色加深效果适用于图片编辑、视频处理等移动端视觉场景。