
GPUImageDarkenBlendFilter代码详解
GPUImageDarkenBlendFilter是安卓开源库GPUImage中用于实现变暗混合(Darken Blend) 的滤镜类,基于OpenGL ES的GLSL着色器实现双纹理像素级混合,核心逻辑是取两个纹理像素中更暗的颜色作为混合结果。
本文将逐行解析代码、讲解核心原理,并给出实际使用示例。
完整代码(逐行注释版)
/*
* Copyright (C) 2018 CyberAgent, Inc. // 版权归属:2018年CyberAgent(日本赛博特工)公司
*
* Licensed under the Apache License, Version 2.0 (the "License"); // 遵循Apache 2.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-2.0 // Apache 2.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. // 协议定义的使用限制
*/
// 包路径:CyberAgent的GPUImage库滤镜模块,所有滤镜类均归属此包
package jp.co.cyberagent.android.gpuimage.filter;
// 继承GPUImageTwoInputFilter:双输入纹理滤镜基类(支持两个纹理混合,如背景+前景)
// 单输入滤镜继承GPUImageFilter,双输入需继承此类
public class GPUImageDarkenBlendFilter extends GPUImageTwoInputFilter {
// 变暗混合的片段着色器常量(GLSL语言),运行在GPU上处理每个像素的颜色
public static final String DARKEN_BLEND_FRAGMENT_SHADER =
"varying highp vec2 textureCoordinate;\\n" + // 变量1:顶点着色器传递的基础纹理(纹理1)坐标,highp=高精度浮点,vec2=二维向量(UV)
" varying highp vec2 textureCoordinate2;\\n" + // 变量2:顶点着色器传递的叠加纹理(纹理2)坐标
"\\n" +
" uniform sampler2D inputImageTexture;\\n" + // 纹理采样器1:绑定基础纹理(如背景图)
" uniform sampler2D inputImageTexture2;\\n" + // 纹理采样器2:绑定叠加纹理(如前景图)
" \\n" +
" void main()\\n" + // GLSL主函数:每个像素都会执行一次,是片段着色器的入口
" {\\n" +
" lowp vec4 base = texture2D(inputImageTexture, textureCoordinate);\\n" + // 采样基础纹理当前像素颜色:texture2D(采样器, 坐标)返回vec4(RGBA),lowp=低精度(减少GPU开销)
" lowp vec4 overlayer = texture2D(inputImageTexture2, textureCoordinate2);\\n" + // 采样叠加纹理当前像素颜色
" \\n" +
" gl_FragColor = vec4(min(overlayer.rgb * base.a, base.rgb * overlayer.a) + overlayer.rgb * (1.0 – base.a) + base.rgb * (1.0 – overlayer.a), 1.0);\\n" + // 核心:计算混合后颜色,赋值给gl_FragColor(GPU内置变量,存储最终像素颜色)
" }";
// 无参构造函数:初始化滤镜
public GPUImageDarkenBlendFilter() {
// 调用父类构造函数,传入自定义片段着色器
// 父类GPUImageTwoInputFilter会自动使用默认的双输入顶点着色器(处理纹理坐标传递)
super(DARKEN_BLEND_FRAGMENT_SHADER);
}
}
代码模块分段解析
1. 版权与许可声明(头部注释)
这是开源项目的标准声明,核心作用:
- 明确版权归属(CyberAgent公司);
- 规定使用协议(Apache 2.0):允许商用、修改、分发,但需保留声明,且软件“按现状”提供,作者不承担责任。
2. 包声明
package jp.co.cyberagent.android.gpuimage.filter; 指定类归属的包路径,GPUImage库的所有滤镜类都集中在filter包下,便于管理和引用。
3. 类定义
public class GPUImageDarkenBlendFilter extends GPUImageTwoInputFilter
- 继承关系:GPUImageTwoInputFilter是处理双输入纹理的基类,适用于“两个纹理混合”的场景(如背景图+前景贴纸混合);若仅处理单纹理(如亮度调整),则继承GPUImageFilter。
- 类功能:实现“变暗混合”——混合两个纹理的像素时,取更暗的颜色值作为最终结果。
4. 片段着色器常量(核心逻辑)
DARKEN_BLEND_FRAGMENT_SHADER是GLSL(OpenGL着色器语言)代码,运行在GPU上,负责计算每个像素的最终颜色,是滤镜的核心。逐行拆解:
| varying highp vec2 textureCoordinate | 顶点着色器传递的基础纹理坐标(UV),varying表示变量在顶点/片段着色器间插值传递,highp保证坐标精度 |
| varying highp vec2 textureCoordinate2 | 顶点着色器传递的叠加纹理坐标(第二个纹理的UV) |
| uniform sampler2D inputImageTexture | 纹理采样器:绑定第一个输入纹理(基础纹理,如背景图),uniform表示整个着色器中值不变 |
| uniform sampler2D inputImageTexture2 | 纹理采样器:绑定第二个输入纹理(叠加纹理,如前景图) |
| void main() | 片段着色器入口,每个像素执行一次 |
| lowp vec4 base = texture2D(…) | 采样基础纹理当前像素的颜色,返回vec4(R, G, B, A)(取值0.0~1.0),lowp降低精度减少GPU开销 |
| lowp vec4 overlayer = texture2D(…) | 采样叠加纹理当前像素的颜色 |
| gl_FragColor = vec4(…) | 核心混合公式,最终像素颜色赋值给gl_FragColor(GPU内置变量) |
混合公式深度解析
min(overlayer.rgb * base.a, base.rgb * overlayer.a) +
overlayer.rgb * (1.0 – base.a) +
base.rgb * (1.0 – overlayer.a)
公式兼顾透明度(Alpha通道) 和变暗混合,拆解:
- 第一部分:min(overlayer.rgb * base.a, base.rgb * overlayer.a) 核心“变暗”逻辑:叠加纹理RGB × 基础纹理透明度 与 基础纹理RGB × 叠加纹理透明度 取最小值(更暗的颜色)。
- 第二部分:overlayer.rgb * (1.0 – base.a) 基础纹理完全透明时(base.a=0),直接显示叠加纹理。
- 第三部分:base.rgb * (1.0 – overlayer.a) 叠加纹理完全透明时(overlayer.a=0),直接显示基础纹理。
- 最终Alpha通道设为1.0(完全不透明),也可根据需求调整为混合后的透明度。
5. 构造函数
public GPUImageDarkenBlendFilter() {
super(DARKEN_BLEND_FRAGMENT_SHADER);
}
- 调用父类GPUImageTwoInputFilter的构造函数,传入自定义的片段着色器;
- 父类会自动加载默认的双输入顶点着色器(负责纹理坐标的传递和顶点渲染),无需重复编写;
- 构造函数执行后,滤镜实例初始化完成,可直接用于纹理混合。
实际使用示例
1. 前置条件
在build.gradle中引入GPUImage库依赖(以最新稳定版为例):
dependencies {
implementation 'jp.co.cyberagent.android:gpuimage:2.1.0'
}
2. 布局文件(显示处理后的图像)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!– GPUImage库的自定义View,用于显示GPU处理后的图像/视频 –>
<jp.co.cyberagent.android.gpuimage.GPUImageView
android:id="@+id/gpuImageView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
3. 代码实现(图片变暗混合)
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import jp.co.cyberagent.android.gpuimage.GPUImage;
import jp.co.cyberagent.android.gpuimage.GPUImageView;
import jp.co.cyberagent.android.gpuimage.filter.GPUImageDarkenBlendFilter;
public class DarkenBlendDemo extends AppCompatActivity {
private GPUImageView gpuImageView;
private GPUImage gpuImage;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_darken_blend);
// 1. 初始化GPUImageView和GPUImage核心类
gpuImageView = findViewById(R.id.gpuImageView);
gpuImage = new GPUImage(this); // GPUImage是滤镜处理的核心入口
gpuImage.setGLSurfaceView(gpuImageView); // 绑定显示View
// 2. 加载两个输入纹理(基础图+叠加图)
// 基础纹理:背景图(res/drawable/background.png)
Bitmap baseBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.background);
// 叠加纹理:前景图(res/drawable/overlay.png)
Bitmap overlayBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.overlay);
// 3. 创建变暗混合滤镜实例
GPUImageDarkenBlendFilter darkenFilter = new GPUImageDarkenBlendFilter();
// 4. 设置滤镜并传入双输入纹理
gpuImage.setFilter(darkenFilter); // 绑定滤镜到GPUImage
// 传入双纹理:参数1=基础纹理,参数2=叠加纹理,参数3=双输入滤镜实例
gpuImage.setImage(baseBitmap, overlayBitmap, darkenFilter);
// 5. 触发渲染,显示混合后的图像
gpuImageView.requestRender();
}
}
4. 使用注意事项
- 纹理尺寸:建议两张位图尺寸一致,若不一致,GPUImage会自动缩放适配,但可能导致拉伸;
- 视频处理:该滤镜也可用于视频/相机预览,只需将GPUImage的输入源改为视频流(如gpuImage.setCamera());
- 自定义扩展:若需调整混合强度,可扩展类添加uniform变量(如mixFactor),在着色器中乘以该因子控制混合程度。
总结
GPUImageDarkenBlendFilter是GPUImage库中典型的双输入混合滤镜,核心设计思路:

网硕互联帮助中心





评论前必须登录!
注册