云计算百科
云计算领域专业知识百科平台

【Android 美颜相机】第二十三天:GPUImageDarkenBlendFilter(变暗混合滤镜)

在这里插入图片描述

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库中典型的双输入混合滤镜,核心设计思路:

  • 复用基类GPUImageTwoInputFilter的双纹理加载、顶点渲染逻辑;
  • 通过自定义GLSL片段着色器实现“变暗混合”的像素级算法;
  • 兼顾透明度处理,保证透明区域的混合效果自然。
  • 在这里插入图片描述

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 【Android 美颜相机】第二十三天:GPUImageDarkenBlendFilter(变暗混合滤镜)
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!