diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser
deleted file mode 100644
index 7d26d3c..0000000
Binary files a/.idea/caches/build_file_checksums.ser and /dev/null differ
diff --git a/.idea/checkstyle-idea.xml b/.idea/checkstyle-idea.xml
deleted file mode 100644
index 19cbb50..0000000
--- a/.idea/checkstyle-idea.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
index 30aa626..681f41a 100644
--- a/.idea/codeStyles/Project.xml
+++ b/.idea/codeStyles/Project.xml
@@ -1,29 +1,116 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+ xmlns:android
+
+ ^$
+
+
+
+
+
+
+
+
+ xmlns:.*
+
+ ^$
+
+
+ BY_NAME
+
+
+
+
+
+
+ .*:id
+
+ http://schemas.android.com/apk/res/android
+
+
+
+
+
+
+
+
+ .*:name
+
+ http://schemas.android.com/apk/res/android
+
+
+
+
+
+
+
+
+ name
+
+ ^$
+
+
+
+
+
+
+
+
+ style
+
+ ^$
+
+
+
+
+
+
+
+
+ .*
+
+ ^$
+
+
+ BY_NAME
+
+
+
+
+
+
+ .*
+
+ http://schemas.android.com/apk/res/android
+
+
+ ANDROID_ATTRIBUTE_ORDER
+
+
+
+
+
+
+ .*
+
+ .*
+
+
+ BY_NAME
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index fc3cdb7..cc71df4 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -9,10 +9,13 @@
+
+
+
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..35c3ada
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 93713f5..9ca2c84 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,49 +1,12 @@
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
- 1.8
-
-
-
-
-
-
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
index 633be07..5f25b1f 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -2,9 +2,14 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
deleted file mode 100644
index 48e5d99..0000000
--- a/app/CMakeLists.txt
+++ /dev/null
@@ -1,146 +0,0 @@
-# For more information about using CMake with Android Studio, read the
-# documentation: https://d.android.com/studio/projects/add-native-code.html
-
-# Sets the minimum version of CMake required to build the native library.
-
-cmake_minimum_required(VERSION 3.4.1)
-
-# Creates and names a library, sets it as either STATIC
-# or SHARED, and provides the relative paths to its source code.
-# You can define multiple libraries, and CMake builds them for you.
-# Gradle automatically packages shared libraries with your APK.
-
-include_directories(${CMAKE_SOURCE_DIR} src/main/cpp)
-add_library( # Sets the name of the library.
- native-lib
-
- # Sets the library as a shared library.
- SHARED
-
- # Provides a relative path to your source file(s).
- src/main/cpp/native-lib.cpp )
-
-add_library( # Sets the name of the library.
- triangle-lib
-
- # Sets the library as a shared library.
- SHARED
-
- # Provides a relative path to your source file(s).
- src/main/cpp/triangle.cpp )
-
-add_library( # Sets the name of the library.
- magicjni
-
- # Sets the library as a shared library.
- SHARED
-
- # Provides a relative path to your source file(s).
- src/main/cpp/magicjni.cpp
- src/main/cpp/utils/OpenglUtils.cpp
- src/main/cpp/utils/Rotation.cpp
- src/main/cpp/utils/TextureRotationUtil.cpp
- src/main/cpp/utils/Matrix.cpp
- src/main/cpp/camera/CameraFilter.cpp
- src/main/cpp/camera/CameraEngine.cpp
- src/main/cpp/image/ImageFilter.cpp
- src/main/cpp/image/ImageInput.cpp
- src/main/cpp/egl/EGLCore.cpp
- src/main/cpp/filter/advanced/MagicAmaroFilter.cpp
- src/main/cpp/filter/advanced/MagicAntiqueFilter.cpp
- src/main/cpp/filter/advanced/MagicBlackCatFilter.cpp
- src/main/cpp/filter/advanced/MagicBrannanFilter.cpp
- src/main/cpp/filter/advanced/MagicBrooklynFilter.cpp
- src/main/cpp/filter/advanced/MagicBeautyFilter.cpp
- src/main/cpp/filter/advanced/MagicCoolFilter.cpp
- src/main/cpp/filter/advanced/MagicCalmFilter.cpp
- src/main/cpp/filter/advanced/MagicCrayonFilter.cpp
- src/main/cpp/filter/advanced/MagicEarlyBirdFilter.cpp
- src/main/cpp/filter/advanced/MagicEmeraldFilter.cpp
- src/main/cpp/filter/advanced/MagicEvergreenFilter.cpp
- src/main/cpp/filter/advanced/MagicFreudFilter.cpp
- src/main/cpp/filter/advanced/MagicFairytableFilter.cpp
- src/main/cpp/filter/advanced/MagicHefeFilter.cpp
- src/main/cpp/filter/advanced/MagicHealthyFilter.cpp
- src/main/cpp/filter/advanced/MagicHudsonFilter.cpp
- src/main/cpp/filter/advanced/MagicInkwellFilter.cpp
- src/main/cpp/filter/advanced/MagicKevinFilter.cpp
- src/main/cpp/filter/advanced/MagicLomoFilter.cpp
- src/main/cpp/filter/advanced/MagicLookupFilter.cpp
- src/main/cpp/filter/advanced/MagicLatteFilter.cpp
- src/main/cpp/filter/advanced/MagicN1977Filter.cpp
- src/main/cpp/filter/advanced/MagicNashvilleFilter.cpp
- src/main/cpp/filter/advanced/MagicNostalgiaFilter.cpp
- src/main/cpp/filter/advanced/MagicNoneFilter.cpp
- src/main/cpp/filter/advanced/MagicPixarFilter.cpp
- src/main/cpp/filter/advanced/MagicRiseFilter.cpp
- src/main/cpp/filter/advanced/MagicRomanceFilter.cpp
- src/main/cpp/filter/advanced/MagicSakuraFilter.cpp
- src/main/cpp/filter/advanced/MagicSierraFilter.cpp
- src/main/cpp/filter/advanced/MagicSketchFilter.cpp
- src/main/cpp/filter/advanced/MagicSkinWhiteFilter.cpp
- src/main/cpp/filter/advanced/MagicSunriseFilter.cpp
- src/main/cpp/filter/advanced/MagicSunsetFilter.cpp
- src/main/cpp/filter/advanced/MagicSutroFilter.cpp
- src/main/cpp/filter/advanced/MagicSweetsFilter.cpp
- src/main/cpp/filter/advanced/MagicTenderFilter.cpp
- src/main/cpp/filter/advanced/MagicToasterFilter.cpp
- src/main/cpp/filter/advanced/MagicValenciaFilter.cpp
- src/main/cpp/filter/advanced/MagicWaldenFilter.cpp
- src/main/cpp/filter/advanced/MagicWarmFilter.cpp
- src/main/cpp/filter/advanced/MagicWhiteCatFilter.cpp
- src/main/cpp/filter/advanced/MagicXproIIFilter.cpp
- src/main/cpp/filter/gpuimage/GpuImageFilter.cpp
-# src/main/cpp/filter/gpuimage/CameraInputFilter.cpp
- src/main/cpp/filter/gpuimage/CameraInputFilterV2.cpp
- src/main/cpp/filter/MagicFilterFactory.cpp
- src/main/cpp/filter/douyin/MagicSoulOutFilter.cpp
- src/main/cpp/filter/douyin/MagicScaleFilter.cpp
- src/main/cpp/filter/douyin/MagicGlitchFilter.cpp
- src/main/cpp/filter/douyin/MagicShakeEffectFilter.cpp
- src/main/cpp/filter/douyin/MagicShineWhiteFilter.cpp
- src/main/cpp/filter/douyin/MagicVerigoFilter.cpp
- src/main/cpp/filter/douyin/RenderBuffer.cpp)
-
-# Searches for a specified prebuilt library and stores the path as a
-# variable. Because CMake includes system libraries in the search path by
-# default, you only need to specify the name of the public NDK library
-# you want to add. CMake verifies that the library exists before
-# completing its build.
-
-find_library( # Sets the name of the path variable.
- log-lib
-
- # Specifies the name of the NDK library that
- # you want CMake to locate.
- log )
-
-# Specifies libraries CMake should link to your target library. You
-# can link multiple libraries, such as libraries you define in this
-# build script, prebuilt third-party libraries, or system libraries.
-
-target_link_libraries( # Specifies the target library.
- native-lib
-
- # Links the target library to the log library
- # included in the NDK.
- ${log-lib} )
-
-target_link_libraries( # Specifies the target library.
- triangle-lib
- android
- GLESv3
-
- # Links the target library to the log library
- # included in the NDK.
- ${log-lib} )
-
-target_link_libraries( # Specifies the target library.
- magicjni
- android
- GLESv3
- EGL
-
- # Links the target library to the log library
- # included in the NDK.
- ${log-lib} )
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index a91702e..b971170 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,25 +1,26 @@
apply plugin: 'com.android.application'
+apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android'
-
apply plugin: 'kotlin-android-extensions'
+
android {
- compileSdkVersion 27
+ compileSdkVersion 28
defaultConfig {
applicationId "com.cangwang.magic"
minSdkVersion 21
- targetSdkVersion 27
+ targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
- externalNativeBuild {
- cmake {
- cppFlags "-std=c++11 -fexceptions"
- }
- }
+// externalNativeBuild {
+// cmake {
+// cppFlags "-std=c++11 -fexceptions"
+// }
+// }
ndk {
- abiFilters "armeabi-v7a"
+ abiFilters "arm64-v8a"
}
}
buildTypes {
@@ -33,11 +34,11 @@ android {
// jniLibs.srcDirs = ['libs']
// }
- externalNativeBuild {
- cmake {
- path "CMakeLists.txt"
- }
- }
+// externalNativeBuild {
+// cmake {
+// path "CMakeLists.txt"
+// }
+// }
compileOptions {
targetCompatibility 1.8
sourceCompatibility 1.8
@@ -48,11 +49,24 @@ android {
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
- implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
- implementation 'com.android.support:appcompat-v7:27.1.1'
- implementation 'com.android.support:design:27.1.1'
+ implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.21'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
- implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
- implementation 'io.reactivex.rxjava2:rxkotlin:2.2.0'
+ implementation ('io.reactivex.rxjava2:rxandroid:2.1.0',{
+ exclude group: 'org.jetbrains.kotlin'
+ })
+ implementation ('io.reactivex.rxjava2:rxkotlin:2.2.0',{
+ exclude group: 'org.jetbrains.kotlin'
+ })
+ api 'com.google.android.play:core:1.4.0'
implementation project(':pickphotoview')
+ kapt "com.alibaba:arouter-compiler:$arouter_compiler_version"
+ implementation project(':base')
+ api project(':filter')
}
+
+kapt {
+ arguments {
+ arg("AROUTER_MODULE_NAME", project.getName())
+ }
+}
+
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1efea8f..b694ee8 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -5,11 +5,12 @@
+
-->
+
\ No newline at end of file
diff --git a/app/src/main/assets/shakeeffect_f.glsl b/app/src/main/assets/shakeeffect_f.glsl
deleted file mode 100644
index 9b15e75..0000000
--- a/app/src/main/assets/shakeeffect_f.glsl
+++ /dev/null
@@ -1,14 +0,0 @@
-#version 300 es
-precision mediump float;
- in vec2 textureCoordinate;
- uniform sampler2D inputImageTexture;
- uniform float uTextureCoordOffset;
- out vec4 glFragColor;
-
- void main()
- {
- vec4 blue = texture(inputImageTexture,textureCoordinate);
- vec4 green = texture(inputImageTexture, vec2(textureCoordinate.x + uTextureCoordOffset, textureCoordinate.y+ uTextureCoordOffset));
- vec4 red = texture(inputImageTexture,vec2(textureCoordinate.x-uTextureCoordOffset,textureCoordinate.y-uTextureCoordOffset));
- glFragColor = vec4(red.r,green.g,blue.b,blue.a);
- }
\ No newline at end of file
diff --git a/app/src/main/cpp/egl/EGLCore.cpp b/app/src/main/cpp/egl/EGLCore.cpp
deleted file mode 100644
index 8da7f39..0000000
--- a/app/src/main/cpp/egl/EGLCore.cpp
+++ /dev/null
@@ -1,117 +0,0 @@
-#include
-#include "EGLCore.h"
-#include
-#include
-
-
-#define LOG_TAG "EGLCore"
-#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
-#define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
-
-/**
- * EGL是介于诸如OpenGL 或OpenVG的Khronos渲染API与底层本地平台窗口系统的接口。它被用于处理图形管理、表面/缓冲捆绑、渲染同步及支援使用其他Khronos API进行的高效、加速、混合模式2D和3D渲染。
- * cangwang 2018.12.1
- */
-EGLCore::EGLCore():mDisplay(EGL_NO_DISPLAY),mSurface(EGL_NO_SURFACE),mContext(EGL_NO_CONTEXT) {
-
-
-}
-
-EGLCore::~EGLCore() {
- mDisplay = EGL_NO_DISPLAY;
- mSurface = EGL_NO_SURFACE;
- mContext = EGL_NO_CONTEXT;
-}
-
-GLboolean EGLCore::buildContext(ANativeWindow *window) {
- //与本地窗口通信
- mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- if (mDisplay == EGL_NO_DISPLAY){
- ALOGE("eglGetDisplay failed: %d",eglGetError());
- return GL_FALSE;
- }
-
- GLint majorVersion;
- GLint minorVersion;
- //获取支持最低和最高版本
- if (!eglInitialize(mDisplay,&majorVersion,&minorVersion)){
- ALOGE("eglInitialize failed: %d",eglGetError());
- return GL_FALSE;
- }
-
- EGLConfig config;
- EGLint numConfigs = 0;
- //颜色使用565,读写类型需要egl扩展
- EGLint attribList[] = {
- EGL_RED_SIZE,5, //指定RGB中的R大小(bits)
- EGL_GREEN_SIZE,6, //指定G大小
- EGL_BLUE_SIZE,5, //指定B大小
- EGL_RENDERABLE_TYPE,EGL_OPENGL_ES3_BIT_KHR, //渲染类型,为相机扩展类型
- EGL_SURFACE_TYPE,EGL_WINDOW_BIT, //绘图类型,
- EGL_NONE
- };
-
- //让EGL推荐匹配的EGLConfig
- if(!eglChooseConfig(mDisplay,attribList,&config,1,&numConfigs)){
- ALOGE("eglChooseConfig failed: %d",eglGetError());
- return GL_FALSE;
- }
-
- //找不到匹配的
- if (numConfigs <1){
- ALOGE("eglChooseConfig get config number less than one");
- return GL_FALSE;
- }
-
- //创建渲染上下文
- //只使用opengles3
- GLint contextAttrib[] = {EGL_CONTEXT_CLIENT_VERSION,3,EGL_NONE};
- // EGL_NO_CONTEXT表示不向其它的context共享资源
- mContext = eglCreateContext(mDisplay,config,EGL_NO_CONTEXT,contextAttrib);
- if (mContext == EGL_NO_CONTEXT){
- ALOGE("eglCreateContext failed: %d",eglGetError());
- return GL_FALSE;
- }
-
- EGLint format = 0;
- if (!eglGetConfigAttrib(mDisplay,config,EGL_NATIVE_VISUAL_ID,&format)){
- ALOGE("eglGetConfigAttrib failed: %d",eglGetError());
- return GL_FALSE;
- }
- ANativeWindow_setBuffersGeometry(window,0,0,format);
-
- //创建On-Screen 渲染区域
- mSurface = eglCreateWindowSurface(mDisplay,config,window,0);
- if (mSurface == EGL_NO_SURFACE){
- ALOGE("eglCreateWindowSurface failed: %d",eglGetError());
- return GL_FALSE;
- }
-
- //把EGLContext和EGLSurface关联起来,单缓冲只使用了一个surface
- if (!eglMakeCurrent(mDisplay,mSurface,mSurface,mContext)){
- ALOGE("eglMakeCurrent failed: %d",eglGetError());
- return GL_FALSE;
- }
-
- ALOGD("buildContext Succeed");
- return GL_TRUE;
-}
-
-/**
- * 现在只使用单缓冲绘制
- */
-void EGLCore::swapBuffer() {
- //双缓冲绘图,原来是检测出前台display和后台缓冲的差别的dirty区域,然后再区域替换buffer
- //1)首先计算非dirty区域,然后将非dirty区域数据从上一个buffer拷贝到当前buffer;
- //2)完成buffer内容的填充,然后将previousBuffer指向buffer,同时queue buffer。
- //3)Dequeue一块新的buffer,并等待fence。如果等待超时,就将buffer cancel掉。
- //4)按需重新计算buffer
- //5)Lock buffer,这样就实现page flip,也就是swapbuffer
- eglSwapBuffers(mDisplay,mSurface);
-}
-
-void EGLCore::release() {
- eglDestroySurface(mDisplay,mSurface);
- eglMakeCurrent(mDisplay,EGL_NO_SURFACE,EGL_NO_SURFACE,EGL_NO_CONTEXT);
- eglDestroyContext(mDisplay,mContext);
-}
\ No newline at end of file
diff --git a/app/src/main/cpp/egl/EGLCore.h b/app/src/main/cpp/egl/EGLCore.h
deleted file mode 100644
index 70272d5..0000000
--- a/app/src/main/cpp/egl/EGLCore.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#include
-#include
-
-#ifndef _EGLCore
-#define _EGLCore
-
-/**
- * cangwang 2018.12.1
- */
-class EGLCore{
-public:
- EGLCore();
-
- ~EGLCore();
-
- GLboolean buildContext(ANativeWindow *window);
-
- void swapBuffer();
-
- void release();
-
-protected:
-
-private:
- EGLDisplay mDisplay;
- EGLSurface mSurface;
- EGLContext mContext;
-};
-
-#endif
diff --git a/app/src/main/cpp/filter/advanced/MagicAmaroFilter.cpp b/app/src/main/cpp/filter/advanced/MagicAmaroFilter.cpp
deleted file mode 100644
index 4ad8a23..0000000
--- a/app/src/main/cpp/filter/advanced/MagicAmaroFilter.cpp
+++ /dev/null
@@ -1,107 +0,0 @@
-#include "MagicAmaroFilter.h"
-#include "src/main/cpp/utils/OpenglUtils.h"
-
-#define LOG_TAG "MagicAmaroFilter"
-#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
-#if DEBUG
-#define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
-#else
-#define ALOGV(...)
-#endif
-
-#define GET_ARRAY_LEN(array,len){len = (sizeof(array) / sizeof(array[0]));}
-
-/**
- * cangwang 2018.12.1
- */
-MagicAmaroFilter::MagicAmaroFilter(){
-
-}
-
-MagicAmaroFilter::MagicAmaroFilter(AAssetManager *assetManager)
- : GPUImageFilter(assetManager,readShaderFromAsset(assetManager,"nofilter_v.glsl"), readShaderFromAsset(assetManager,"amaro.glsl")){
- GET_ARRAY_LEN(inputTextureHandles,len);
-}
-
-MagicAmaroFilter::~MagicAmaroFilter() {
-
-}
-
-void MagicAmaroFilter::onDestroy() {
- glDeleteTextures(len,inputTextureHandles);
- *inputTextureHandles={0};
-}
-
-void MagicAmaroFilter::onDrawArraysPre() {
- glUniform1f(mGLStrengthLocation, 1.0f);
-// for (int i = 0; i < len; ++i) {
-// if (inputTextureHandles[i] != 0) {
-// glActiveTexture(static_cast(GL_TEXTURE3 + i));
-// glBindTexture(GL_TEXTURE_2D, inputTextureHandles[i]);
-// glUniform1i(inputTextureUniformLocations[i], i+3);
-// }
-// }
- if (inputTextureHandles[0] != 0) {
- glActiveTexture(GL_TEXTURE3);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[0]);
- glUniform1i(inputTextureUniformLocations[0], 3);
- }
-
- if (inputTextureHandles[1] != 0) {
- glActiveTexture(GL_TEXTURE4);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[1]);
- glUniform1i(inputTextureUniformLocations[1], 4);
- }
-
- if (inputTextureHandles[2] != 0) {
- glActiveTexture(GL_TEXTURE5);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[2]);
- glUniform1i(inputTextureUniformLocations[2], 5);
- }
-}
-
-void MagicAmaroFilter::onDrawArraysAfter() {
-// for (int i = 0; i < len; ++i) {
-// if (inputTextureHandles[i] != 0) {
-// glActiveTexture(static_cast(GL_TEXTURE3 + i));
-// glBindTexture(GL_TEXTURE_2D, inputTextureHandles[i]);
-// glActiveTexture(GL_TEXTURE0);
-// }
-// }
- if (inputTextureHandles[0] != 0) {
- glActiveTexture(GL_TEXTURE3);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[0]);
- glActiveTexture(GL_TEXTURE0);
- }
-
- if (inputTextureHandles[1] != 0) {
- glActiveTexture(GL_TEXTURE4);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[1]);
- glActiveTexture(GL_TEXTURE0);
- }
-
- if (inputTextureHandles[2] != 0) {
- glActiveTexture(GL_TEXTURE5);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[2]);
- glActiveTexture(GL_TEXTURE0);
- }
-}
-
-
-void MagicAmaroFilter::onInit() {
- GPUImageFilter::onInit();
-// for (int i = 0; i < len; ++i) {
-// inputTextureUniformLocations[i] = glGetUniformLocation(mGLProgId,"inputImageTexture"+(2+i));
-// }
- inputTextureUniformLocations[0] = glGetUniformLocation(mGLProgId,"inputImageTexture2");
- inputTextureUniformLocations[1] = glGetUniformLocation(mGLProgId,"inputImageTexture3");
- inputTextureUniformLocations[2] = glGetUniformLocation(mGLProgId,"inputImageTexture4");
- mGLStrengthLocation = glGetUniformLocation(mGLProgId,"strength");
-}
-
-void MagicAmaroFilter::onInitialized() {
- GPUImageFilter::onInitialized();
- inputTextureHandles[0] = loadTextureFromAssets(mAssetManager,"brannan_blowout.png");
- inputTextureHandles[1] = loadTextureFromAssets(mAssetManager,"overlaymap.png");
- inputTextureHandles[2] = loadTextureFromAssets(mAssetManager,"amaromap.png");
-}
\ No newline at end of file
diff --git a/app/src/main/cpp/filter/advanced/MagicBrannanFilter.cpp b/app/src/main/cpp/filter/advanced/MagicBrannanFilter.cpp
deleted file mode 100644
index 5fdfc7e..0000000
--- a/app/src/main/cpp/filter/advanced/MagicBrannanFilter.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-#include "MagicBrannanFilter.h"
-#include "src/main/cpp/utils/OpenglUtils.h"
-
-#define LOG_TAG "MagicBrannanFilter"
-#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
-#if DEBUG
-#define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
-#else
-#define ALOGV(...)
-#endif
-
-#define GET_ARRAY_LEN(array,len){len = (sizeof(array) / sizeof(array[0]));}
-
-/**
- * cangwang 2018.12.1
- */
-MagicBrannanFilter::MagicBrannanFilter(){
-
-}
-
-MagicBrannanFilter::MagicBrannanFilter(AAssetManager *assetManager)
- : GPUImageFilter(assetManager,readShaderFromAsset(assetManager,"nofilter_v.glsl"), readShaderFromAsset(assetManager,"brannan.glsl")){
- GET_ARRAY_LEN(inputTextureHandles,len);
-}
-
-MagicBrannanFilter::~MagicBrannanFilter() {
-
-}
-
-void MagicBrannanFilter::onDestroy() {
- glDeleteTextures(len,inputTextureHandles);
- *inputTextureHandles= {0};
-}
-
-void MagicBrannanFilter::onDrawArraysPre() {
- glUniform1f(mGLStrengthLocation, 1.0f);
-// for (int i = 0; i < len; ++i) {
-// if (inputTextureHandles[i] != 0) {
-// glActiveTexture(GL_TEXTURE3 + i);
-// glBindTexture(GL_TEXTURE_2D, inputTextureHandles[i]);
-// glUniform1i(inputTextureUniformLocations[i], i+3);
-// }
-// }
- if (inputTextureHandles[0] != 0) {
- glActiveTexture(GL_TEXTURE3);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[0]);
- glUniform1i(inputTextureUniformLocations[0], 3);
- }
-
- if (inputTextureHandles[1] != 0) {
- glActiveTexture(GL_TEXTURE4);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[1]);
- glUniform1i(inputTextureUniformLocations[1], 4);
- }
-
- if (inputTextureHandles[2] != 0) {
- glActiveTexture(GL_TEXTURE5);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[2]);
- glUniform1i(inputTextureUniformLocations[2], 5);
- }
-
- if (inputTextureHandles[3] != 0) {
- glActiveTexture(GL_TEXTURE6);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[3]);
- glUniform1i(inputTextureUniformLocations[3], 6);
- }
- if (inputTextureHandles[4] != 0) {
- glActiveTexture(GL_TEXTURE7);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[4]);
- glUniform1i(inputTextureUniformLocations[4], 7);
- }
-}
-
-void MagicBrannanFilter::onDrawArraysAfter() {
-// for (int i = 0; i < len; ++i) {
-// if (inputTextureHandles[i] != 0) {
-// glActiveTexture(GL_TEXTURE3 + i);
-// glBindTexture(GL_TEXTURE_2D, inputTextureHandles[i]);
-// glActiveTexture(GL_TEXTURE0);
-// }
-// }
-
- if (inputTextureHandles[0] != 0) {
- glActiveTexture(GL_TEXTURE3);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[0]);
- glActiveTexture(GL_TEXTURE0);
- }
-
- if (inputTextureHandles[1] != 0) {
- glActiveTexture(GL_TEXTURE4);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[1]);
- glActiveTexture(GL_TEXTURE0);
- }
-
- if (inputTextureHandles[2] != 0) {
- glActiveTexture(GL_TEXTURE5);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[2]);
- glActiveTexture(GL_TEXTURE0);
- }
-
- if (inputTextureHandles[3] != 0) {
- glActiveTexture(GL_TEXTURE6);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[3]);
- glActiveTexture(GL_TEXTURE0);
- }
-
- if (inputTextureHandles[4] != 0) {
- glActiveTexture(GL_TEXTURE7);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[4]);
- glActiveTexture(GL_TEXTURE0);
- }
-}
-
-
-void MagicBrannanFilter::onInit() {
- GPUImageFilter::onInit();
-// for (int i = 0; i < len; ++i) {
-// inputTextureUniformLocations[i] = glGetUniformLocation(mGLProgId,"inputImageTexture"+(2+i));
-// }
- inputTextureUniformLocations[0] = glGetUniformLocation(mGLProgId,"inputImageTexture2");
- inputTextureUniformLocations[1] = glGetUniformLocation(mGLProgId,"inputImageTexture3");
- inputTextureUniformLocations[2] = glGetUniformLocation(mGLProgId,"inputImageTexture4");
- inputTextureUniformLocations[3] = glGetUniformLocation(mGLProgId,"inputImageTexture5");
- inputTextureUniformLocations[4] = glGetUniformLocation(mGLProgId,"inputImageTexture6");
- mGLStrengthLocation = glGetUniformLocation(mGLProgId,"strength");
-}
-
-void MagicBrannanFilter::onInitialized() {
- GPUImageFilter::onInitialized();
- inputTextureHandles[0] = loadTextureFromAssets(mAssetManager,"brannan_process.png");
- inputTextureHandles[1] = loadTextureFromAssets(mAssetManager,"brannan_blowout.png");
- inputTextureHandles[2] = loadTextureFromAssets(mAssetManager,"brannan_contrast.png");
- inputTextureHandles[3] = loadTextureFromAssets(mAssetManager,"brannan_luma.png");
- inputTextureHandles[4] = loadTextureFromAssets(mAssetManager,"brannan_screen.png");
-
-}
\ No newline at end of file
diff --git a/app/src/main/cpp/filter/advanced/MagicBrooklynFilter.cpp b/app/src/main/cpp/filter/advanced/MagicBrooklynFilter.cpp
deleted file mode 100644
index 1e65eda..0000000
--- a/app/src/main/cpp/filter/advanced/MagicBrooklynFilter.cpp
+++ /dev/null
@@ -1,107 +0,0 @@
-#include "MagicBrooklynFilter.h"
-#include "src/main/cpp/utils/OpenglUtils.h"
-
-#define LOG_TAG "MagicBrooklynFilter"
-#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
-#if DEBUG
-#define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
-#else
-#define ALOGV(...)
-#endif
-
-#define GET_ARRAY_LEN(array,len){len = (sizeof(array) / sizeof(array[0]));}
-
-/**
- * cangwang 2018.12.1
- */
-MagicBrooklynFilter::MagicBrooklynFilter(){
-
-}
-
-MagicBrooklynFilter::MagicBrooklynFilter(AAssetManager *assetManager)
- : GPUImageFilter(assetManager,readShaderFromAsset(assetManager,"nofilter_v.glsl"), readShaderFromAsset(assetManager,"brooklyn.glsl")){
- GET_ARRAY_LEN(inputTextureHandles,len);
-}
-
-MagicBrooklynFilter::~MagicBrooklynFilter() {
-
-}
-
-void MagicBrooklynFilter::onDestroy() {
- glDeleteTextures(len,inputTextureHandles);
- *inputTextureHandles={0};
-}
-
-void MagicBrooklynFilter::onDrawArraysPre() {
- glUniform1f(mGLStrengthLocation, 1.0f);
-// for (int i = 0; i < len; ++i) {
-// if (inputTextureHandles[i] != 0) {
-// glActiveTexture(static_cast(GL_TEXTURE3 + i));
-// glBindTexture(GL_TEXTURE_2D, inputTextureHandles[i]);
-// glUniform1i(inputTextureUniformLocations[i], 3);
-// }
-// }
- if (inputTextureHandles[0] != 0) {
- glActiveTexture(GL_TEXTURE3);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[0]);
- glUniform1i(inputTextureUniformLocations[0], 3);
- }
-
- if (inputTextureHandles[1] != 0) {
- glActiveTexture(GL_TEXTURE4);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[1]);
- glUniform1i(inputTextureUniformLocations[1], 4);
- }
-
- if (inputTextureHandles[2] != 0) {
- glActiveTexture(GL_TEXTURE5);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[2]);
- glUniform1i(inputTextureUniformLocations[2], 5);
- }
-}
-
-void MagicBrooklynFilter::onDrawArraysAfter() {
-// for (int i = 0; i < len; ++i) {
-// if (inputTextureHandles[i] != 0) {
-// glActiveTexture(static_cast(GL_TEXTURE3 + i));
-// glBindTexture(GL_TEXTURE_2D, inputTextureHandles[i]);
-// glActiveTexture(GL_TEXTURE0);
-// }
-// }
- if (inputTextureHandles[0] != 0) {
- glActiveTexture(GL_TEXTURE3);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[0]);
- glActiveTexture(GL_TEXTURE0);
- }
-
- if (inputTextureHandles[1] != 0) {
- glActiveTexture(GL_TEXTURE4);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[1]);
- glActiveTexture(GL_TEXTURE0);
- }
-
- if (inputTextureHandles[2] != 0) {
- glActiveTexture(GL_TEXTURE5);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[2]);
- glActiveTexture(GL_TEXTURE0);
- }
-}
-
-
-void MagicBrooklynFilter::onInit() {
- GPUImageFilter::onInit();
-// for (int i = 0; i < len; ++i) {
-// inputTextureUniformLocations[i] = glGetUniformLocation(mGLProgId,"inputImageTexture"+(2+i));
-// }
- inputTextureUniformLocations[0] = glGetUniformLocation(mGLProgId,"inputImageTexture2");
- inputTextureUniformLocations[1] = glGetUniformLocation(mGLProgId,"inputImageTexture3");
- inputTextureUniformLocations[2] = glGetUniformLocation(mGLProgId,"inputImageTexture4");
- mGLStrengthLocation = glGetUniformLocation(mGLProgId,"strength");
-}
-
-void MagicBrooklynFilter::onInitialized() {
- GPUImageFilter::onInitialized();
- inputTextureHandles[0] = loadTextureFromAssets(mAssetManager,"brooklynCurves1.png");
- inputTextureHandles[1] = loadTextureFromAssets(mAssetManager,"filter_map_first.png");
- inputTextureHandles[2] = loadTextureFromAssets(mAssetManager,"brooklynCurves2.png");
-}
\ No newline at end of file
diff --git a/app/src/main/cpp/filter/advanced/MagicEarlyBirdFilter.cpp b/app/src/main/cpp/filter/advanced/MagicEarlyBirdFilter.cpp
deleted file mode 100644
index 330002d..0000000
--- a/app/src/main/cpp/filter/advanced/MagicEarlyBirdFilter.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-#include "MagicEarlyBirdFilter.h"
-#include "src/main/cpp/utils/OpenglUtils.h"
-
-#define LOG_TAG "MagicEarlyBirdFilter"
-#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
-#if DEBUG
-#define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
-#else
-#define ALOGV(...)
-#endif
-
-#define GET_ARRAY_LEN(array,len){len = (sizeof(array) / sizeof(array[0]));}
-
-/**
- * cangwang 2018.12.1
- */
-MagicEarlyBirdFilter::MagicEarlyBirdFilter(){
-
-}
-
-MagicEarlyBirdFilter::MagicEarlyBirdFilter(AAssetManager *assetManager)
- : GPUImageFilter(assetManager,readShaderFromAsset(assetManager,"nofilter_v.glsl"), readShaderFromAsset(assetManager,"brannan.glsl")){
- GET_ARRAY_LEN(inputTextureHandles,len);
-}
-
-MagicEarlyBirdFilter::~MagicEarlyBirdFilter() {
-
-}
-
-void MagicEarlyBirdFilter::onDestroy() {
- glDeleteTextures(len,inputTextureHandles);
- *inputTextureHandles={0};
-}
-
-void MagicEarlyBirdFilter::onDrawArraysPre() {
- glUniform1f(mGLStrengthLocation, 1.0f);
-// for (int i = 0; i < len; ++i) {
-// if (inputTextureHandles[i] != 0) {
-// glActiveTexture(static_cast(GL_TEXTURE3 + i));
-// glBindTexture(GL_TEXTURE_2D, inputTextureHandles[i]);
-// glUniform1i(inputTextureUniformLocations[i], (i+3));
-// }
-// }
- if (inputTextureHandles[0] != 0) {
- glActiveTexture(GL_TEXTURE3);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[0]);
- glUniform1i(inputTextureUniformLocations[0], 3);
- }
-
- if (inputTextureHandles[1] != 0) {
- glActiveTexture(GL_TEXTURE4);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[1]);
- glUniform1i(inputTextureUniformLocations[1], 4);
- }
-
- if (inputTextureHandles[2] != 0) {
- glActiveTexture(GL_TEXTURE5);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[2]);
- glUniform1i(inputTextureUniformLocations[2], 5);
- }
-
- if (inputTextureHandles[3] != 0) {
- glActiveTexture(GL_TEXTURE6);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[3]);
- glUniform1i(inputTextureUniformLocations[3], 6);
- }
- if (inputTextureHandles[4] != 0) {
- glActiveTexture(GL_TEXTURE7);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[4]);
- glUniform1i(inputTextureUniformLocations[4], 7);
- }
-}
-
-void MagicEarlyBirdFilter::onDrawArraysAfter() {
-// for (int i = 0; i < len; ++i) {
-// if (inputTextureHandles[i] != 0) {
-// glActiveTexture(static_cast(GL_TEXTURE3 + i));
-// glBindTexture(GL_TEXTURE_2D, inputTextureHandles[i]);
-// glActiveTexture(GL_TEXTURE0);
-// }
-// }
- if (inputTextureHandles[0] != 0) {
- glActiveTexture(GL_TEXTURE3);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[0]);
- glActiveTexture(GL_TEXTURE0);
- }
-
- if (inputTextureHandles[1] != 0) {
- glActiveTexture(GL_TEXTURE4);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[1]);
- glActiveTexture(GL_TEXTURE0);
- }
-
- if (inputTextureHandles[2] != 0) {
- glActiveTexture(GL_TEXTURE5);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[2]);
- glActiveTexture(GL_TEXTURE0);
- }
-
- if (inputTextureHandles[3] != 0) {
- glActiveTexture(GL_TEXTURE6);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[3]);
- glActiveTexture(GL_TEXTURE0);
- }
-
- if (inputTextureHandles[4] != 0) {
- glActiveTexture(GL_TEXTURE7);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[4]);
- glActiveTexture(GL_TEXTURE0);
- }
-}
-
-
-void MagicEarlyBirdFilter::onInit() {
- GPUImageFilter::onInit();
-// for (int i = 0; i < len; ++i) {
-// inputTextureUniformLocations[i] = glGetUniformLocation(mGLProgId,"inputImageTexture"+(2+i));
-// }
- inputTextureUniformLocations[0] = glGetUniformLocation(mGLProgId,"inputImageTexture2");
- inputTextureUniformLocations[1] = glGetUniformLocation(mGLProgId,"inputImageTexture3");
- inputTextureUniformLocations[2] = glGetUniformLocation(mGLProgId,"inputImageTexture4");
- inputTextureUniformLocations[3] = glGetUniformLocation(mGLProgId,"inputImageTexture5");
- inputTextureUniformLocations[4] = glGetUniformLocation(mGLProgId,"inputImageTexture6");
- mGLStrengthLocation = glGetUniformLocation(mGLProgId,"strength");
-}
-
-void MagicEarlyBirdFilter::onInitialized() {
- GPUImageFilter::onInitialized();
-
- inputTextureHandles[0] = loadTextureFromAssets(mAssetManager,"earlybirdcurves.png");
- inputTextureHandles[1] = loadTextureFromAssets(mAssetManager,"earlybirdoverlaymap_new.png");
- inputTextureHandles[2] = loadTextureFromAssets(mAssetManager,"vignettemap_new.png");
- inputTextureHandles[3] = loadTextureFromAssets(mAssetManager,"earlybirdblowout.png");
- inputTextureHandles[4] = loadTextureFromAssets(mAssetManager,"earlybirdmap.png");
-
-}
\ No newline at end of file
diff --git a/app/src/main/cpp/filter/advanced/MagicHefeFilter.cpp b/app/src/main/cpp/filter/advanced/MagicHefeFilter.cpp
deleted file mode 100644
index 98e85cd..0000000
--- a/app/src/main/cpp/filter/advanced/MagicHefeFilter.cpp
+++ /dev/null
@@ -1,134 +0,0 @@
-#include "MagicHefeFilter.h"
-#include "src/main/cpp/utils/OpenglUtils.h"
-
-#define LOG_TAG "MagicHefeFilter"
-#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
-#define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
-
-#define GET_ARRAY_LEN(array,len){len = (sizeof(array) / sizeof(array[0]));}
-
-/**
- * cangwang 2018.12.1
- */
-MagicHefeFilter::MagicHefeFilter(){
-
-}
-
-MagicHefeFilter::MagicHefeFilter(AAssetManager *assetManager)
- : GPUImageFilter(assetManager,readShaderFromAsset(assetManager,"nofilter_v.glsl"), readShaderFromAsset(assetManager,"hefe.glsl")){
-// GET_ARRAY_LEN(inputTextureHandles,len);
-}
-
-MagicHefeFilter::~MagicHefeFilter() {
-
-}
-
-void MagicHefeFilter::onDestroy() {
-// glDeleteTextures(len,inputTextureHandles);
-// *inputTextureHandles={0};
- glDeleteTextures(1,&inputTextureHandles[0]);
- glDeleteTextures(1,&inputTextureHandles[1]);
- glDeleteTextures(1,&inputTextureHandles[2]);
- glDeleteTextures(1,&inputTextureHandles[3]);
- inputTextureHandles[0] =0;
- inputTextureHandles[1] =0;
- inputTextureHandles[2] =0;
- inputTextureHandles[3] =0;
-}
-
-void MagicHefeFilter::onDrawArraysPre() {
-// ALOGV("onDrawArraysAfter len",len);
-// for (int i = 0; i < len; ++i) {
-// if (inputTextureHandles[i] != 0) {
-// glActiveTexture(static_cast(GL_TEXTURE3 + i));
-// glBindTexture(GL_TEXTURE_2D, inputTextureHandles[i]);
-// glUniform1i(inputTextureUniformLocations[i], (i+3));
-// ALOGV("onDrawArraysPre inputTextureUniformLocations[%d]",i);
-// }
-// }
- glUniform1f(mGLStrengthLocation, 1.0f);
- if (inputTextureHandles[0] != 0) {
- glActiveTexture(GL_TEXTURE3);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[0]);
- glUniform1i(inputTextureUniformLocations[0], 3);
- }
-
- if (inputTextureHandles[1] != 0) {
- glActiveTexture(GL_TEXTURE4);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[1]);
- glUniform1i(inputTextureUniformLocations[1], 4);
- }
-
- if (inputTextureHandles[2] != 0) {
- glActiveTexture(GL_TEXTURE5);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[2]);
- glUniform1i(inputTextureUniformLocations[2], 5);
- }
-
- if (inputTextureHandles[3] != 0) {
- glActiveTexture(GL_TEXTURE6);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[3]);
- glUniform1i(inputTextureUniformLocations[3], 6);
- }
-}
-
-void MagicHefeFilter::onDrawArraysAfter() {
-// ALOGV("onDrawArraysAfter len",len);
-// for (int i = 0; i < len; ++i) {
-// if (inputTextureHandles[i] != 0) {
-// glActiveTexture(static_cast(GL_TEXTURE3 + i));
-// glBindTexture(GL_TEXTURE_2D, inputTextureHandles[i]);
-// glActiveTexture(GL_TEXTURE0);
-// ALOGV("onDrawArraysAfter inputTextureHandles[%d]",i);
-// }
-// }
-
- if (inputTextureHandles[0] != 0) {
- glActiveTexture(GL_TEXTURE3);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[0]);
- glActiveTexture(GL_TEXTURE0);
- }
-
- if (inputTextureHandles[1] != 0) {
- glActiveTexture(GL_TEXTURE4);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[1]);
- glActiveTexture(GL_TEXTURE0);
- }
-
- if (inputTextureHandles[2] != 0) {
- glActiveTexture(GL_TEXTURE5);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[2]);
- glActiveTexture(GL_TEXTURE0);
- }
-
- if (inputTextureHandles[3] != 0) {
- glActiveTexture(GL_TEXTURE6);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[3]);
- glActiveTexture(GL_TEXTURE0);
- }
-}
-
-
-void MagicHefeFilter::onInit() {
- GPUImageFilter::onInit();
-// for (int i = 0; i < len; ++i) {
-// inputTextureUniformLocations[i] = glGetUniformLocation(mGLProgId,"inputImageTexture"+(2+i));
-// }
- inputTextureUniformLocations[0] = glGetUniformLocation(mGLProgId,"inputImageTexture2");
- inputTextureUniformLocations[1] = glGetUniformLocation(mGLProgId,"inputImageTexture3");
- inputTextureUniformLocations[2] = glGetUniformLocation(mGLProgId,"inputImageTexture4");
- inputTextureUniformLocations[3] = glGetUniformLocation(mGLProgId,"inputImageTexture5");
- mGLStrengthLocation = glGetUniformLocation(mGLProgId,"strength");
-}
-
-void MagicHefeFilter::onInitialized() {
- GPUImageFilter::onInitialized();
-// inputTextureHandles[0] = loadTextureFromAssets(mAssetManager,"rise_mask1.jpg");
-// inputTextureHandles[1] = loadTextureFromAssets(mAssetManager,"hefemap.png");
-// inputTextureHandles[2] = loadTextureFromAssets(mAssetManager,"rise_mask2.jpg");
-// inputTextureHandles[3] = loadTextureFromAssets(mAssetManager,"hefesoftlight.png");
- inputTextureHandles[0] = loadTextureFromAssets(mAssetManager,"edgeburn.png");
- inputTextureHandles[1] = loadTextureFromAssets(mAssetManager,"hefemap.png");
- inputTextureHandles[2] = loadTextureFromAssets(mAssetManager,"hefemetal.png");
- inputTextureHandles[3] = loadTextureFromAssets(mAssetManager,"hefesoftlight.png");
-}
\ No newline at end of file
diff --git a/app/src/main/cpp/filter/advanced/MagicLomoFilter.cpp b/app/src/main/cpp/filter/advanced/MagicLomoFilter.cpp
deleted file mode 100644
index 4c79242..0000000
--- a/app/src/main/cpp/filter/advanced/MagicLomoFilter.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-#include "MagicLomoFilter.h"
-#include "src/main/cpp/utils/OpenglUtils.h"
-
-#define LOG_TAG "MagicLomoFilter"
-#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
-#if DEBUG
-#define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
-#else
-#define ALOGV(...)
-#endif
-
-#define GET_ARRAY_LEN(array,len){len = (sizeof(array) / sizeof(array[0]));}
-
-/**
- * cangwang 2018.12.1
- */
-MagicLomoFilter::MagicLomoFilter(){
-
-}
-
-MagicLomoFilter::MagicLomoFilter(AAssetManager *assetManager)
- : GPUImageFilter(assetManager,readShaderFromAsset(assetManager,"nofilter_v.glsl"), readShaderFromAsset(assetManager,"lomo.glsl")){
- GET_ARRAY_LEN(inputTextureHandles,len);
-}
-
-MagicLomoFilter::~MagicLomoFilter() {
-
-}
-
-void MagicLomoFilter::onDestroy() {
- glDeleteTextures(len,inputTextureHandles);
- *inputTextureHandles={0};
-}
-
-void MagicLomoFilter::onDrawArraysPre() {
- glUniform1f(mGLStrengthLocation, 1.0f);
-// for (int i = 0; i < len; ++i) {
-// if (inputTextureHandles[i] != 0) {
-// glActiveTexture(static_cast(GL_TEXTURE3 + i));
-// glBindTexture(GL_TEXTURE_2D, inputTextureHandles[i]);
-// glUniform1i(inputTextureUniformLocations[i], (i+3));
-// }
-// }
- if (inputTextureHandles[0] != 0) {
- glActiveTexture(GL_TEXTURE3);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[0]);
- glUniform1i(inputTextureUniformLocations[0], 3);
- }
-
- if (inputTextureHandles[1] != 0) {
- glActiveTexture(GL_TEXTURE4);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[1]);
- glUniform1i(inputTextureUniformLocations[1], 4);
- }
-}
-
-void MagicLomoFilter::onDrawArraysAfter() {
-// for (int i = 0; i < len; ++i) {
-// if (inputTextureHandles[i] != 0) {
-// glActiveTexture(static_cast(GL_TEXTURE3 + i));
-// glBindTexture(GL_TEXTURE_2D, inputTextureHandles[i]);
-// glActiveTexture(GL_TEXTURE0);
-// }
-// }
- if (inputTextureHandles[0] != 0) {
- glActiveTexture(GL_TEXTURE3);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[0]);
- glActiveTexture(GL_TEXTURE0);
- }
-
- if (inputTextureHandles[1] != 0) {
- glActiveTexture(GL_TEXTURE4);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[1]);
- glActiveTexture(GL_TEXTURE0);
- }
-}
-
-
-void MagicLomoFilter::onInit() {
- GPUImageFilter::onInit();
-// for (int i = 0; i < len; ++i) {
-// inputTextureUniformLocations[i] = glGetUniformLocation(mGLProgId,"inputImageTexture"+(2+i));
-// }
- inputTextureUniformLocations[0] = glGetUniformLocation(mGLProgId,"inputImageTexture2");
- inputTextureUniformLocations[1] = glGetUniformLocation(mGLProgId,"inputImageTexture3");
- mGLStrengthLocation = glGetUniformLocation(mGLProgId,"strength");
-}
-
-void MagicLomoFilter::onInitialized() {
- GPUImageFilter::onInitialized();
-
- inputTextureHandles[0] = loadTextureFromAssets(mAssetManager,"lomomap_new.png");
- inputTextureHandles[1] = loadTextureFromAssets(mAssetManager,"vignette_map.png");
-}
\ No newline at end of file
diff --git a/app/src/main/cpp/filter/advanced/MagicN1977Filter.cpp b/app/src/main/cpp/filter/advanced/MagicN1977Filter.cpp
deleted file mode 100644
index 279abdb..0000000
--- a/app/src/main/cpp/filter/advanced/MagicN1977Filter.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-#include "MagicN1977Filter.h"
-#include "src/main/cpp/utils/OpenglUtils.h"
-
-#define LOG_TAG "MagicN1977Filter"
-#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
-#if DEBUG
-#define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
-#else
-#define ALOGV(...)
-#endif
-
-#define GET_ARRAY_LEN(array,len){len = (sizeof(array) / sizeof(array[0]));}
-
-/**
- * cangwang 2018.12.1
- */
-MagicN1977Filter::MagicN1977Filter(){
-
-}
-
-MagicN1977Filter::MagicN1977Filter(AAssetManager *assetManager)
- : GPUImageFilter(assetManager,readShaderFromAsset(assetManager,"nofilter_v.glsl"), readShaderFromAsset(assetManager,"n1977.glsl")){
- GET_ARRAY_LEN(inputTextureHandles,len);
-}
-
-MagicN1977Filter::~MagicN1977Filter() {
-
-}
-
-void MagicN1977Filter::onDestroy() {
- glDeleteTextures(len,inputTextureHandles);
- *inputTextureHandles={0};
-}
-
-void MagicN1977Filter::onDrawArraysPre() {
- glUniform1f(mGLStrengthLocation, 1.0f);
-// for (int i = 0; i < len; ++i) {
-// if (inputTextureHandles[i] != 0) {
-// glActiveTexture(static_cast(GL_TEXTURE3 + i));
-// glBindTexture(GL_TEXTURE_2D, inputTextureHandles[i]);
-// glUniform1i(inputTextureUniformLocations[i], (i+3));
-// }
-// }
- if (inputTextureHandles[0] != 0) {
- glActiveTexture(GL_TEXTURE3);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[0]);
- glUniform1i(inputTextureUniformLocations[0], 3);
- }
-
- if (inputTextureHandles[1] != 0) {
- glActiveTexture(GL_TEXTURE4);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[1]);
- glUniform1i(inputTextureUniformLocations[1], 4);
- }
-}
-
-void MagicN1977Filter::onDrawArraysAfter() {
-// for (int i = 0; i < len; ++i) {
-// if (inputTextureHandles[i] != 0) {
-// glActiveTexture(static_cast(GL_TEXTURE3 + i));
-// glBindTexture(GL_TEXTURE_2D, inputTextureHandles[i]);
-// glActiveTexture(GL_TEXTURE0);
-// }
-// }
- if (inputTextureHandles[0] != 0) {
- glActiveTexture(GL_TEXTURE3);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[0]);
- glActiveTexture(GL_TEXTURE0);
- }
-
- if (inputTextureHandles[1] != 0) {
- glActiveTexture(GL_TEXTURE4);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[1]);
- glActiveTexture(GL_TEXTURE0);
- }
-}
-
-
-void MagicN1977Filter::onInit() {
- GPUImageFilter::onInit();
-// for (int i = 0; i < len; ++i) {
-// inputTextureUniformLocations[i] = glGetUniformLocation(mGLProgId,"inputImageTexture"+(2+i));
-// }
- inputTextureUniformLocations[0] = glGetUniformLocation(mGLProgId,"inputImageTexture2");
- inputTextureUniformLocations[1] = glGetUniformLocation(mGLProgId,"inputImageTexture3");
- mGLStrengthLocation = glGetUniformLocation(mGLProgId,"strength");
-}
-
-void MagicN1977Filter::onInitialized() {
- GPUImageFilter::onInitialized();
-
- inputTextureHandles[0] = loadTextureFromAssets(mAssetManager,"n1977map.png");
- inputTextureHandles[1] = loadTextureFromAssets(mAssetManager,"n1977blowout.png");
-}
\ No newline at end of file
diff --git a/app/src/main/cpp/filter/advanced/MagicRiseFilter.cpp b/app/src/main/cpp/filter/advanced/MagicRiseFilter.cpp
deleted file mode 100644
index 7a9153e..0000000
--- a/app/src/main/cpp/filter/advanced/MagicRiseFilter.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-#include "MagicRiseFilter.h"
-#include "src/main/cpp/utils/OpenglUtils.h"
-
-#define LOG_TAG "MagicRiseFilter"
-#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
-#if DEBUG
-#define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
-#else
-#define ALOGV(...)
-#endif
-
-#define GET_ARRAY_LEN(array,len){len = (sizeof(array) / sizeof(array[0]));}
-
-/**
- * cangwang 2018.12.1
- */
-MagicRiseFilter::MagicRiseFilter(){
-
-}
-
-MagicRiseFilter::MagicRiseFilter(AAssetManager *assetManager)
- : GPUImageFilter(assetManager,readShaderFromAsset(assetManager,"nofilter_v.glsl"), readShaderFromAsset(assetManager,"rise.glsl")){
- GET_ARRAY_LEN(inputTextureHandles,len);
-}
-
-MagicRiseFilter::~MagicRiseFilter() {
-
-}
-
-void MagicRiseFilter::onDestroy() {
- glDeleteTextures(len,inputTextureHandles);
- *inputTextureHandles={0};
-}
-
-void MagicRiseFilter::onDrawArraysPre() {
- glUniform1f(mGLStrengthLocation, 1.0f);
-// for (int i = 0; i < len; ++i) {
-// if (inputTextureHandles[i] != 0) {
-// glActiveTexture(static_cast(GL_TEXTURE3 + i));
-// glBindTexture(GL_TEXTURE_2D, inputTextureHandles[i]);
-// glUniform1i(inputTextureUniformLocations[i], i+3);
-// }
-// }
- if (inputTextureHandles[0] != 0) {
- glActiveTexture(GL_TEXTURE3);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[0]);
- glUniform1i(inputTextureUniformLocations[0], 3);
- }
-
- if (inputTextureHandles[1] != 0) {
- glActiveTexture(GL_TEXTURE4);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[1]);
- glUniform1i(inputTextureUniformLocations[1], 4);
- }
-
- if (inputTextureHandles[2] != 0) {
- glActiveTexture(GL_TEXTURE5);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[2]);
- glUniform1i(inputTextureUniformLocations[2], 5);
- }
-}
-
-void MagicRiseFilter::onDrawArraysAfter() {
-// for (int i = 0; i < len; ++i) {
-// if (inputTextureHandles[i] != 0) {
-// glActiveTexture(static_cast(GL_TEXTURE3 + i));
-// glBindTexture(GL_TEXTURE_2D, inputTextureHandles[i]);
-// glActiveTexture(GL_TEXTURE0);
-// }
-// }
- if (inputTextureHandles[0] != 0) {
- glActiveTexture(GL_TEXTURE3);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[0]);
- glActiveTexture(GL_TEXTURE0);
- }
-
- if (inputTextureHandles[1] != 0) {
- glActiveTexture(GL_TEXTURE4);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[1]);
- glActiveTexture(GL_TEXTURE0);
- }
-
- if (inputTextureHandles[2] != 0) {
- glActiveTexture(GL_TEXTURE5);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[2]);
- glActiveTexture(GL_TEXTURE0);
- }
-}
-
-
-void MagicRiseFilter::onInit() {
- GPUImageFilter::onInit();
-
-// for (int i = 0; i < len; ++i) {
-// inputTextureUniformLocations[i] = glGetUniformLocation(mGLProgId,"inputImageTexture"+(2+i));
-// }
- inputTextureUniformLocations[0] = glGetUniformLocation(mGLProgId,"inputImageTexture2");
- inputTextureUniformLocations[1] = glGetUniformLocation(mGLProgId,"inputImageTexture3");
- inputTextureUniformLocations[2] = glGetUniformLocation(mGLProgId,"inputImageTexture4");
- mGLStrengthLocation = glGetUniformLocation(mGLProgId,"strength");
-}
-
-void MagicRiseFilter::onInitialized() {
- GPUImageFilter::onInitialized();
- inputTextureHandles[0] = loadTextureFromAssets(mAssetManager,"blackboard1024.png");
- inputTextureHandles[1] = loadTextureFromAssets(mAssetManager,"overlaymap.png");
- inputTextureHandles[2] = loadTextureFromAssets(mAssetManager,"risemap.png");
-}
\ No newline at end of file
diff --git a/app/src/main/cpp/filter/advanced/MagicSierraFilter.cpp b/app/src/main/cpp/filter/advanced/MagicSierraFilter.cpp
deleted file mode 100644
index 1b515d7..0000000
--- a/app/src/main/cpp/filter/advanced/MagicSierraFilter.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-#include "MagicSierraFilter.h"
-#include "src/main/cpp/utils/OpenglUtils.h"
-
-#define LOG_TAG "MagicSierraFilter"
-#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
-#if DEBUG
-#define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
-#else
-#define ALOGV(...)
-#endif
-
-#define GET_ARRAY_LEN(array,len){len = (sizeof(array) / sizeof(array[0]));}
-
-/**
- * cangwang 2018.12.1
- */
-MagicSierraFilter::MagicSierraFilter(){
-
-}
-
-MagicSierraFilter::MagicSierraFilter(AAssetManager *assetManager)
- : GPUImageFilter(assetManager,readShaderFromAsset(assetManager,"nofilter_v.glsl"), readShaderFromAsset(assetManager,"sierra.glsl")){
- GET_ARRAY_LEN(inputTextureHandles,len);
-}
-
-MagicSierraFilter::~MagicSierraFilter() {
-
-}
-
-void MagicSierraFilter::onDestroy() {
- glDeleteTextures(len,inputTextureHandles);
- *inputTextureHandles={0};
-}
-
-void MagicSierraFilter::onDrawArraysPre() {
- glUniform1f(mGLStrengthLocation, 1.0f);
-// for (int i = 0; i < len; ++i) {
-// if (inputTextureHandles[i] != 0) {
-// glActiveTexture(static_cast(GL_TEXTURE3 + i));
-// glBindTexture(GL_TEXTURE_2D, inputTextureHandles[i]);
-// glUniform1i(inputTextureUniformLocations[i], i+3);
-// }
-// }
- if (inputTextureHandles[0] != 0) {
- glActiveTexture(GL_TEXTURE3);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[0]);
- glUniform1i(inputTextureUniformLocations[0], 3);
- }
-
- if (inputTextureHandles[1] != 0) {
- glActiveTexture(GL_TEXTURE4);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[1]);
- glUniform1i(inputTextureUniformLocations[1], 4);
- }
-
- if (inputTextureHandles[2] != 0) {
- glActiveTexture(GL_TEXTURE5);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[2]);
- glUniform1i(inputTextureUniformLocations[2], 5);
- }
-}
-
-void MagicSierraFilter::onDrawArraysAfter() {
-// for (int i = 0; i < len; ++i) {
-// if (inputTextureHandles[i] != 0) {
-// glActiveTexture(static_cast(GL_TEXTURE3 + i));
-// glBindTexture(GL_TEXTURE_2D, inputTextureHandles[i]);
-// glActiveTexture(GL_TEXTURE0);
-// }
-// }
- if (inputTextureHandles[0] != 0) {
- glActiveTexture(GL_TEXTURE3);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[0]);
- glActiveTexture(GL_TEXTURE0);
- }
-
- if (inputTextureHandles[1] != 0) {
- glActiveTexture(GL_TEXTURE4);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[1]);
- glActiveTexture(GL_TEXTURE0);
- }
-
- if (inputTextureHandles[2] != 0) {
- glActiveTexture(GL_TEXTURE5);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[2]);
- glActiveTexture(GL_TEXTURE0);
- }
-}
-
-
-void MagicSierraFilter::onInit() {
- GPUImageFilter::onInit();
-
-// for (int i = 0; i < len; ++i) {
-// inputTextureUniformLocations[i] = glGetUniformLocation(mGLProgId,"inputImageTexture"+(2+i));
-// }
- inputTextureUniformLocations[0] = glGetUniformLocation(mGLProgId,"inputImageTexture2");
- inputTextureUniformLocations[1] = glGetUniformLocation(mGLProgId,"inputImageTexture3");
- inputTextureUniformLocations[2] = glGetUniformLocation(mGLProgId,"inputImageTexture4");
- mGLStrengthLocation = glGetUniformLocation(mGLProgId,"strength");
-}
-
-void MagicSierraFilter::onInitialized() {
- GPUImageFilter::onInitialized();
- inputTextureHandles[0] = loadTextureFromAssets(mAssetManager,"sierravignette.png");
- inputTextureHandles[1] = loadTextureFromAssets(mAssetManager,"overlaymap.png");
- inputTextureHandles[2] = loadTextureFromAssets(mAssetManager,"sierramap.png");
-}
\ No newline at end of file
diff --git a/app/src/main/cpp/filter/advanced/MagicSutroFilter.cpp b/app/src/main/cpp/filter/advanced/MagicSutroFilter.cpp
deleted file mode 100644
index 152a019..0000000
--- a/app/src/main/cpp/filter/advanced/MagicSutroFilter.cpp
+++ /dev/null
@@ -1,135 +0,0 @@
-#include "MagicSutroFilter.h"
-#include "src/main/cpp/utils/OpenglUtils.h"
-
-#define LOG_TAG "MagicSutroFilter"
-#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
-#if DEBUG
-#define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
-#else
-#define ALOGV(...)
-#endif
-
-#define GET_ARRAY_LEN(array,len){len = (sizeof(array) / sizeof(array[0]));}
-
-/**
- * cangwang 2018.12.1
- */
-MagicSutroFilter::MagicSutroFilter(){
-
-}
-
-MagicSutroFilter::MagicSutroFilter(AAssetManager *assetManager)
- : GPUImageFilter(assetManager,readShaderFromAsset(assetManager,"nofilter_v.glsl"), readShaderFromAsset(assetManager,"sutro.glsl")){
- GET_ARRAY_LEN(inputTextureHandles,len);
-}
-
-MagicSutroFilter::~MagicSutroFilter() {
-
-}
-
-void MagicSutroFilter::onDestroy() {
- glDeleteTextures(len,inputTextureHandles);
- *inputTextureHandles={0};
-}
-
-void MagicSutroFilter::onDrawArraysPre() {
- glUniform1f(mGLStrengthLocation, 1.0f);
-// for (int i = 0; i < len; ++i) {
-// if (inputTextureHandles[i] != 0) {
-// glActiveTexture(static_cast(GL_TEXTURE3 + i));
-// glBindTexture(GL_TEXTURE_2D, inputTextureHandles[i]);
-// glUniform1i(inputTextureUniformLocations[i], i+3);
-// }
-// }
- if (inputTextureHandles[0] != 0) {
- glActiveTexture(GL_TEXTURE3);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[0]);
- glUniform1i(inputTextureUniformLocations[0], 3);
- }
-
- if (inputTextureHandles[1] != 0) {
- glActiveTexture(GL_TEXTURE4);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[1]);
- glUniform1i(inputTextureUniformLocations[1], 4);
- }
-
- if (inputTextureHandles[2] != 0) {
- glActiveTexture(GL_TEXTURE5);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[2]);
- glUniform1i(inputTextureUniformLocations[2], 5);
- }
-
- if (inputTextureHandles[3] != 0) {
- glActiveTexture(GL_TEXTURE6);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[3]);
- glUniform1i(inputTextureUniformLocations[3], 6);
- }
- if (inputTextureHandles[4] != 0) {
- glActiveTexture(GL_TEXTURE7);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[4]);
- glUniform1i(inputTextureUniformLocations[4], 7);
- }
-}
-
-void MagicSutroFilter::onDrawArraysAfter() {
-// for (int i = 0; i < len; ++i) {
-// if (inputTextureHandles[i] != 0) {
-// glActiveTexture(static_cast(GL_TEXTURE3 + i));
-// glBindTexture(GL_TEXTURE_2D, inputTextureHandles[i]);
-// glActiveTexture(GL_TEXTURE0);
-// }
-// }
- if (inputTextureHandles[0] != 0) {
- glActiveTexture(GL_TEXTURE3);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[0]);
- glActiveTexture(GL_TEXTURE0);
- }
-
- if (inputTextureHandles[1] != 0) {
- glActiveTexture(GL_TEXTURE4);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[1]);
- glActiveTexture(GL_TEXTURE0);
- }
-
- if (inputTextureHandles[2] != 0) {
- glActiveTexture(GL_TEXTURE5);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[2]);
- glActiveTexture(GL_TEXTURE0);
- }
-
- if (inputTextureHandles[3] != 0) {
- glActiveTexture(GL_TEXTURE6);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[3]);
- glActiveTexture(GL_TEXTURE0);
- }
-
- if (inputTextureHandles[4] != 0) {
- glActiveTexture(GL_TEXTURE7);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[4]);
- glActiveTexture(GL_TEXTURE0);
- }
-}
-
-
-void MagicSutroFilter::onInit() {
- GPUImageFilter::onInit();
-// for (int i = 0; i < len; ++i) {
-// inputTextureUniformLocations[i] = glGetUniformLocation(mGLProgId,"inputImageTexture"+(2+i));
-// }
- inputTextureUniformLocations[0] = glGetUniformLocation(mGLProgId,"inputImageTexture2");
- inputTextureUniformLocations[1] = glGetUniformLocation(mGLProgId,"inputImageTexture3");
- inputTextureUniformLocations[2] = glGetUniformLocation(mGLProgId,"inputImageTexture4");
- inputTextureUniformLocations[3] = glGetUniformLocation(mGLProgId,"inputImageTexture5");
- inputTextureUniformLocations[4] = glGetUniformLocation(mGLProgId,"inputImageTexture6");
- mGLStrengthLocation = glGetUniformLocation(mGLProgId,"strength");
-}
-
-void MagicSutroFilter::onInitialized() {
- GPUImageFilter::onInitialized();
- inputTextureHandles[0] = loadTextureFromAssets(mAssetManager,"vignette_map.png");
- inputTextureHandles[1] = loadTextureFromAssets(mAssetManager,"sutrometal.png");
- inputTextureHandles[2] = loadTextureFromAssets(mAssetManager,"softlight.png");
- inputTextureHandles[3] = loadTextureFromAssets(mAssetManager,"sutroedgeburn.png");
- inputTextureHandles[4] = loadTextureFromAssets(mAssetManager,"sutrocurves.png");
-
-}
\ No newline at end of file
diff --git a/app/src/main/cpp/filter/advanced/MagicToasterFilter.cpp b/app/src/main/cpp/filter/advanced/MagicToasterFilter.cpp
deleted file mode 100644
index bc50daa..0000000
--- a/app/src/main/cpp/filter/advanced/MagicToasterFilter.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-#include "MagicToasterFilter.h"
-#include "src/main/cpp/utils/OpenglUtils.h"
-
-#define LOG_TAG "MagicToasterFilter"
-#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
-#if DEBUG
-#define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
-#else
-#define ALOGV(...)
-#endif
-
-#define GET_ARRAY_LEN(array,len){len = (sizeof(array) / sizeof(array[0]));}
-
-/**
- * cangwang 2018.12.1
- */
-MagicToasterFilter::MagicToasterFilter(){
-
-}
-
-MagicToasterFilter::MagicToasterFilter(AAssetManager *assetManager)
- : GPUImageFilter(assetManager,readShaderFromAsset(assetManager,"nofilter_v.glsl"), readShaderFromAsset(assetManager,"toaster2_filter_shader.glsl")){
- GET_ARRAY_LEN(inputTextureHandles,len);
-}
-
-MagicToasterFilter::~MagicToasterFilter() {
-
-}
-
-void MagicToasterFilter::onDestroy() {
- glDeleteTextures(len,inputTextureHandles);
- *inputTextureHandles={0};
-}
-
-void MagicToasterFilter::onDrawArraysPre() {
- glUniform1f(mGLStrengthLocation, 1.0f);
-// for (int i = 0; i < len; ++i) {
-// if (inputTextureHandles[i] != 0) {
-// glActiveTexture(static_cast(GL_TEXTURE3 + i));
-// glBindTexture(GL_TEXTURE_2D, inputTextureHandles[i]);
-// glUniform1i(inputTextureUniformLocations[i], i+3);
-// }
-// }
- if (inputTextureHandles[0] != 0) {
- glActiveTexture(GL_TEXTURE3);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[0]);
- glUniform1i(inputTextureUniformLocations[0], 3);
- }
-
- if (inputTextureHandles[1] != 0) {
- glActiveTexture(GL_TEXTURE4);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[1]);
- glUniform1i(inputTextureUniformLocations[1], 4);
- }
-
- if (inputTextureHandles[2] != 0) {
- glActiveTexture(GL_TEXTURE5);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[2]);
- glUniform1i(inputTextureUniformLocations[2], 5);
- }
-
- if (inputTextureHandles[3] != 0) {
- glActiveTexture(GL_TEXTURE6);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[3]);
- glUniform1i(inputTextureUniformLocations[3], 6);
- }
- if (inputTextureHandles[4] != 0) {
- glActiveTexture(GL_TEXTURE7);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[4]);
- glUniform1i(inputTextureUniformLocations[4], 7);
- }
-
-}
-
-void MagicToasterFilter::onDrawArraysAfter() {
-// for (int i = 0; i < len; ++i) {
-// if (inputTextureHandles[i] != 0) {
-// glActiveTexture(static_cast(GL_TEXTURE3 + i));
-// glBindTexture(GL_TEXTURE_2D, inputTextureHandles[i]);
-// glActiveTexture(GL_TEXTURE0);
-// }
-// }
- if (inputTextureHandles[0] != 0) {
- glActiveTexture(GL_TEXTURE3);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[0]);
- glActiveTexture(GL_TEXTURE0);
- }
-
- if (inputTextureHandles[1] != 0) {
- glActiveTexture(GL_TEXTURE4);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[1]);
- glActiveTexture(GL_TEXTURE0);
- }
-
- if (inputTextureHandles[2] != 0) {
- glActiveTexture(GL_TEXTURE5);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[2]);
- glActiveTexture(GL_TEXTURE0);
- }
-
- if (inputTextureHandles[3] != 0) {
- glActiveTexture(GL_TEXTURE6);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[3]);
- glActiveTexture(GL_TEXTURE0);
- }
-
- if (inputTextureHandles[4] != 0) {
- glActiveTexture(GL_TEXTURE7);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[4]);
- glActiveTexture(GL_TEXTURE0);
- }
-}
-
-
-void MagicToasterFilter::onInit() {
- GPUImageFilter::onInit();
-// for (int i = 0; i < len; ++i) {
-// inputTextureUniformLocations[i] = glGetUniformLocation(mGLProgId,"inputImageTexture"+(2+i));
-// }
- inputTextureUniformLocations[0] = glGetUniformLocation(mGLProgId,"inputImageTexture2");
- inputTextureUniformLocations[1] = glGetUniformLocation(mGLProgId,"inputImageTexture3");
- inputTextureUniformLocations[2] = glGetUniformLocation(mGLProgId,"inputImageTexture4");
- inputTextureUniformLocations[3] = glGetUniformLocation(mGLProgId,"inputImageTexture5");
- inputTextureUniformLocations[4] = glGetUniformLocation(mGLProgId,"inputImageTexture6");
- mGLStrengthLocation = glGetUniformLocation(mGLProgId,"strength");
-}
-
-void MagicToasterFilter::onInitialized() {
- GPUImageFilter::onInitialized();
- inputTextureHandles[0] = loadTextureFromAssets(mAssetManager,"toastermetal.png");
- inputTextureHandles[1] = loadTextureFromAssets(mAssetManager,"toastersoftlight.png");
- inputTextureHandles[2] = loadTextureFromAssets(mAssetManager,"toastercurves.png");
- inputTextureHandles[3] = loadTextureFromAssets(mAssetManager,"toasteroverlaymapwarm.png");
- inputTextureHandles[4] = loadTextureFromAssets(mAssetManager,"toastercolorshift.png");
-
-}
\ No newline at end of file
diff --git a/app/src/main/cpp/filter/advanced/MagicValenciaFilter.cpp b/app/src/main/cpp/filter/advanced/MagicValenciaFilter.cpp
deleted file mode 100644
index d269f57..0000000
--- a/app/src/main/cpp/filter/advanced/MagicValenciaFilter.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-#include "MagicValenciaFilter.h"
-#include "src/main/cpp/utils/OpenglUtils.h"
-
-#define LOG_TAG "MagicValenciaFilter"
-#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
-#if DEBUG
-#define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
-#else
-#define ALOGV(...)
-#endif
-
-#define GET_ARRAY_LEN(array,len){len = (sizeof(array) / sizeof(array[0]));}
-
-/**
- * cangwang 2018.12.1
- */
-MagicValenciaFilter::MagicValenciaFilter(){
-
-}
-
-MagicValenciaFilter::MagicValenciaFilter(AAssetManager *assetManager)
- : GPUImageFilter(assetManager,readShaderFromAsset(assetManager,"nofilter_v.glsl"), readShaderFromAsset(assetManager,"valencia.glsl")){
- GET_ARRAY_LEN(inputTextureHandles,len);
-}
-
-MagicValenciaFilter::~MagicValenciaFilter() {
-
-}
-
-void MagicValenciaFilter::onDestroy() {
- glDeleteTextures(len,inputTextureHandles);
- *inputTextureHandles={0};
-}
-
-void MagicValenciaFilter::onDrawArraysPre() {
- glUniform1f(mGLStrengthLocation, 1.0f);
-// for (int i = 0; i < len; ++i) {
-// if (inputTextureHandles[i] != 0) {
-// glActiveTexture(static_cast(GL_TEXTURE3 + i));
-// glBindTexture(GL_TEXTURE_2D, inputTextureHandles[i]);
-// glUniform1i(inputTextureUniformLocations[i], i+3);
-// }
-// }
- if (inputTextureHandles[0] != 0) {
- glActiveTexture(GL_TEXTURE3);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[0]);
- glUniform1i(inputTextureUniformLocations[0], 3);
- }
-
- if (inputTextureHandles[1] != 0) {
- glActiveTexture(GL_TEXTURE4);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[1]);
- glUniform1i(inputTextureUniformLocations[1], 4);
- }
-}
-
-void MagicValenciaFilter::onDrawArraysAfter() {
-// for (int i = 0; i < len; ++i) {
-// if (inputTextureHandles[i] != 0) {
-// glActiveTexture(static_cast(GL_TEXTURE3 + i));
-// glBindTexture(GL_TEXTURE_2D, inputTextureHandles[i]);
-// glActiveTexture(GL_TEXTURE0);
-// }
-// }
- if (inputTextureHandles[0] != 0) {
- glActiveTexture(GL_TEXTURE3);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[0]);
- glActiveTexture(GL_TEXTURE0);
- }
-
- if (inputTextureHandles[1] != 0) {
- glActiveTexture(GL_TEXTURE4);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[1]);
- glActiveTexture(GL_TEXTURE0);
- }
-}
-
-
-void MagicValenciaFilter::onInit() {
- GPUImageFilter::onInit();
-// for (int i = 0; i < len; ++i) {
-// inputTextureUniformLocations[i] = glGetUniformLocation(mGLProgId,"inputImageTexture"+(2+i));
-// }
- inputTextureUniformLocations[0] = glGetUniformLocation(mGLProgId,"inputImageTexture2");
- inputTextureUniformLocations[1] = glGetUniformLocation(mGLProgId,"inputImageTexture3");
- mGLStrengthLocation = glGetUniformLocation(mGLProgId,"strength");
-}
-
-void MagicValenciaFilter::onInitialized() {
- GPUImageFilter::onInitialized();
- inputTextureHandles[0] = loadTextureFromAssets(mAssetManager,"valenciamap.png");
- inputTextureHandles[1] = loadTextureFromAssets(mAssetManager,"valenciagradientmap.png");
-}
\ No newline at end of file
diff --git a/app/src/main/cpp/filter/advanced/MagicWaldenFilter.cpp b/app/src/main/cpp/filter/advanced/MagicWaldenFilter.cpp
deleted file mode 100644
index 225c2ff..0000000
--- a/app/src/main/cpp/filter/advanced/MagicWaldenFilter.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-#include "MagicWaldenFilter.h"
-#include "src/main/cpp/utils/OpenglUtils.h"
-
-#define LOG_TAG "MagicWaldenFilter"
-#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
-#if DEBUG
-#define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
-#else
-#define ALOGV(...)
-#endif
-
-#define GET_ARRAY_LEN(array,len){len = (sizeof(array) / sizeof(array[0]));}
-
-/**
- * cangwang 2018.12.1
- */
-MagicWaldenFilter::MagicWaldenFilter(){
-
-}
-
-MagicWaldenFilter::MagicWaldenFilter(AAssetManager *assetManager)
- : GPUImageFilter(assetManager,readShaderFromAsset(assetManager,"nofilter_v.glsl"), readShaderFromAsset(assetManager,"walden.glsl")){
- GET_ARRAY_LEN(inputTextureHandles,len);
-}
-
-MagicWaldenFilter::~MagicWaldenFilter() {
-
-}
-
-void MagicWaldenFilter::onDestroy() {
- glDeleteTextures(len,inputTextureHandles);
- *inputTextureHandles={0};
-}
-
-void MagicWaldenFilter::onDrawArraysPre() {
- glUniform1f(mGLStrengthLocation, 1.0f);
-// for (int i = 0; i < len; ++i) {
-// if (inputTextureHandles[i] != 0) {
-// glActiveTexture(static_cast(GL_TEXTURE3 + i));
-// glBindTexture(GL_TEXTURE_2D, inputTextureHandles[i]);
-// glUniform1i(inputTextureUniformLocations[i], i+3);
-// }
-// }
- if (inputTextureHandles[0] != 0) {
- glActiveTexture(GL_TEXTURE3);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[0]);
- glUniform1i(inputTextureUniformLocations[0], 3);
- }
-
- if (inputTextureHandles[1] != 0) {
- glActiveTexture(GL_TEXTURE4);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[1]);
- glUniform1i(inputTextureUniformLocations[1], 4);
- }
-}
-
-void MagicWaldenFilter::onDrawArraysAfter() {
-// for (int i = 0; i < len; ++i) {
-// if (inputTextureHandles[i] != 0) {
-// glActiveTexture(static_cast(GL_TEXTURE3 + i));
-// glBindTexture(GL_TEXTURE_2D, inputTextureHandles[i]);
-// glActiveTexture(GL_TEXTURE0);
-// }
-// }
- if (inputTextureHandles[0] != 0) {
- glActiveTexture(GL_TEXTURE3);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[0]);
- glActiveTexture(GL_TEXTURE0);
- }
-
- if (inputTextureHandles[1] != 0) {
- glActiveTexture(GL_TEXTURE4);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[1]);
- glActiveTexture(GL_TEXTURE0);
- }
-}
-
-
-void MagicWaldenFilter::onInit() {
- GPUImageFilter::onInit();
-// for (int i = 0; i < len; ++i) {
-// inputTextureUniformLocations[i] = glGetUniformLocation(mGLProgId,"inputImageTexture"+(2+i));
-// }
- inputTextureUniformLocations[0] = glGetUniformLocation(mGLProgId,"inputImageTexture2");
- inputTextureUniformLocations[1] = glGetUniformLocation(mGLProgId,"inputImageTexture3");
- mGLStrengthLocation = glGetUniformLocation(mGLProgId,"strength");
-}
-
-void MagicWaldenFilter::onInitialized() {
- GPUImageFilter::onInitialized();
- inputTextureHandles[0] = loadTextureFromAssets(mAssetManager,"walden_map.png");
- inputTextureHandles[1] = loadTextureFromAssets(mAssetManager,"vignette_map.png");
-}
\ No newline at end of file
diff --git a/app/src/main/cpp/filter/advanced/MagicXproIIFilter.cpp b/app/src/main/cpp/filter/advanced/MagicXproIIFilter.cpp
deleted file mode 100644
index 2a0c853..0000000
--- a/app/src/main/cpp/filter/advanced/MagicXproIIFilter.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-#include "MagicXproIIFilter.h"
-#include "src/main/cpp/utils/OpenglUtils.h"
-
-#define LOG_TAG "MagicXproIIFilter"
-#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
-#if DEBUG
-#define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
-#else
-#define ALOGV(...)
-#endif
-
-#define GET_ARRAY_LEN(array,len){len = (sizeof(array) / sizeof(array[0]));}
-
-/**
- * cangwang 2018.12.1
- */
-MagicXproIIFilter::MagicXproIIFilter(){
-
-}
-
-MagicXproIIFilter::MagicXproIIFilter(AAssetManager *assetManager)
- : GPUImageFilter(assetManager,readShaderFromAsset(assetManager,"nofilter_v.glsl"), readShaderFromAsset(assetManager,"xproii_filter_shader.glsl")){
- GET_ARRAY_LEN(inputTextureHandles,len);
-}
-
-MagicXproIIFilter::~MagicXproIIFilter() {
-
-}
-
-void MagicXproIIFilter::onDestroy() {
- glDeleteTextures(len,inputTextureHandles);
- *inputTextureHandles={0};
-}
-
-void MagicXproIIFilter::onDrawArraysPre() {
- glUniform1f(mGLStrengthLocation, 1.0f);
-// for (int i = 0; i < len; ++i) {
-// if (inputTextureHandles[i] != 0) {
-// glActiveTexture(static_cast(GL_TEXTURE3 + i));
-// glBindTexture(GL_TEXTURE_2D, inputTextureHandles[i]);
-// glUniform1i(inputTextureUniformLocations[i], i+3);
-// }
-// }
- if (inputTextureHandles[0] != 0) {
- glActiveTexture(GL_TEXTURE3);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[0]);
- glUniform1i(inputTextureUniformLocations[0], 3);
- }
-
- if (inputTextureHandles[1] != 0) {
- glActiveTexture(GL_TEXTURE4);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[1]);
- glUniform1i(inputTextureUniformLocations[1], 4);
- }
-}
-
-void MagicXproIIFilter::onDrawArraysAfter() {
-// for (int i = 0; i < len; ++i) {
-// if (inputTextureHandles[i] != 0) {
-// glActiveTexture(static_cast(GL_TEXTURE3 + i));
-// glBindTexture(GL_TEXTURE_2D, inputTextureHandles[i]);
-// glActiveTexture(GL_TEXTURE0);
-// }
-// }
- if (inputTextureHandles[0] != 0) {
- glActiveTexture(GL_TEXTURE3);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[0]);
- glActiveTexture(GL_TEXTURE0);
- }
-
- if (inputTextureHandles[1] != 0) {
- glActiveTexture(GL_TEXTURE4);
- glBindTexture(GL_TEXTURE_2D, inputTextureHandles[1]);
- glActiveTexture(GL_TEXTURE0);
- }
-}
-
-
-void MagicXproIIFilter::onInit() {
- GPUImageFilter::onInit();
-// for (int i = 0; i < len; ++i) {
-// inputTextureUniformLocations[i] = glGetUniformLocation(mGLProgId,"inputImageTexture"+(2+i));
-// }
- inputTextureUniformLocations[0] = glGetUniformLocation(mGLProgId,"inputImageTexture2");
- inputTextureUniformLocations[1] = glGetUniformLocation(mGLProgId,"inputImageTexture3");
- mGLStrengthLocation = glGetUniformLocation(mGLProgId,"strength");
-}
-
-void MagicXproIIFilter::onInitialized() {
- GPUImageFilter::onInitialized();
- inputTextureHandles[0] = loadTextureFromAssets(mAssetManager,"xpromap.png");
- inputTextureHandles[1] = loadTextureFromAssets(mAssetManager,"vignettemap_new.png");
-}
\ No newline at end of file
diff --git a/app/src/main/cpp/magicjni.cpp b/app/src/main/cpp/magicjni.cpp
deleted file mode 100644
index 0aab6db..0000000
--- a/app/src/main/cpp/magicjni.cpp
+++ /dev/null
@@ -1,301 +0,0 @@
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include "src/main/cpp/camera/CameraEngine.h"
-#include "src/main/cpp/camera/CameraFilter.h"
-
-#define LOG_TAG "magicjni"
-#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
-#define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
-extern "C" {
-
-std::mutex gMutex;
-CameraEngine *glCamera = nullptr;
-CameraFilter *glCameraFilter = nullptr;
-ImageFilter *glImageFilter = nullptr;
-AAssetManager *aAssetManager = nullptr;
-
-JNIEXPORT jint JNICALL
-Java_com_cangwang_magic_util_OpenGLJniLib_magicBaseInit(JNIEnv *env, jobject obj,
- jobject surface,jint width,jint height,jobject assetManager) {
- std::unique_lock lock(gMutex);
- if(glCamera){
- glCamera->stop();
- delete glCamera;
- }
- //创建window
- ANativeWindow *window = ANativeWindow_fromSurface(env,surface);
- //获取文件管理
- AAssetManager *manager = AAssetManager_fromJava(env,assetManager);
- glCamera = new CameraEngine(window);
- glCamera->setAssetManager(manager);
- glCamera->resize(width,height);
- return glCamera->create();
-}
-
-
-JNIEXPORT void JNICALL
-Java_com_cangwang_magic_util_OpenGLJniLib_magicBaseCreate(JNIEnv *env, jobject obj) {
- //关闭颜色抖动 若机器的分辨率已经相当高,激活抖动操作根本就没有任何意义
- glDisable(GL_DITHER);
- //清颜色
- glClearColor(0.0,0.0,0.0,0.0);
- //开启剔除操作效果 在多边形中使用
- glEnable(GL_CULL_FACE);
- //开启深度测试
- glEnable(GL_DEPTH_TEST);
-}
-
-JNIEXPORT void JNICALL
-Java_com_cangwang_magic_util_OpenGLJniLib_magicBaseChange(JNIEnv *env, jobject obj,jint width,jint height) {
- //视口变换,可视区域
- if(glCamera)
- glCamera->resize(width,height);
-}
-
-JNIEXPORT void JNICALL
-Java_com_cangwang_magic_util_OpenGLJniLib_magicBaseDraw(JNIEnv *env, jobject obj,jfloatArray matrix_) {
- jfloat *matrix = env->GetFloatArrayElements(matrix_,NULL);
-
- std::unique_lock lock(gMutex);
- if (!glCamera){
- ALOGE("draw error, glCamera is null");
- return;
- }
- glCamera->draw(matrix);
- env->ReleaseFloatArrayElements(matrix_,matrix,0);
-}
-
-JNIEXPORT void JNICALL
-Java_com_cangwang_magic_util_OpenGLJniLib_magicBaseRelease(JNIEnv *env, jobject obj) {
- std::unique_lock lock(gMutex);
- if (glCamera){
- glCamera->stop();
- delete glCamera;
- glCamera = nullptr;
- }
-}
-
-JNIEXPORT void JNICALL
-Java_com_cangwang_magic_util_OpenGLJniLib_magicAdjustSize(JNIEnv *env, jobject obj,jint orientation,jboolean isFront,jboolean flipVertical) {
-
-}
-
-//相机滤镜surfaceView初始化的时候创建
-JNIEXPORT jint JNICALL
-Java_com_cangwang_magic_util_OpenGLJniLib_magicFilterCreate(JNIEnv *env, jobject obj,
- jobject surface,jobject assetManager) {
- std::unique_lock lock(gMutex);
- if(glCameraFilter){ //停止摄像头采集并销毁
- glCameraFilter->stop();
- delete glCameraFilter;
- }
-
- //初始化native window
- ANativeWindow *window = ANativeWindow_fromSurface(env,surface);
- //初始化app内获取数据管理
- aAssetManager= AAssetManager_fromJava(env,assetManager);
- //初始化相机采集
- glCameraFilter = new CameraFilter(window,aAssetManager);
- //创建
- return glCameraFilter->create();
-}
-
-JNIEXPORT void JNICALL
-Java_com_cangwang_magic_util_OpenGLJniLib_magicFilterSet(JNIEnv *env, jobject obj,
- jobject surface,jobject assetManager) {
- std::unique_lock lock(gMutex);
- if (!glCameraFilter){
- ALOGE("filter set error, glCameraFilter is null");
- return;
- }
- AAssetManager *manager = AAssetManager_fromJava(env,assetManager);
- glCameraFilter->setFilter(manager);
-}
-
-//窗口大小设置,SurfaceView初始化后会触发一次
-JNIEXPORT void JNICALL
-Java_com_cangwang_magic_util_OpenGLJniLib_magicFilterChange(JNIEnv *env, jobject obj,jint width,jint height) {
- std::unique_lock lock(gMutex);
- //视口变换,可视区域
- if (!glCameraFilter){
- ALOGE("change error, glCameraFilter is null");
- return;
- }
- //更改窗口大小
- glCameraFilter->change(width,height);
-}
-
-JNIEXPORT void JNICALL
-Java_com_cangwang_magic_util_OpenGLJniLib_magicFilterDraw(JNIEnv *env, jobject obj,jfloatArray matrix_,jstring address) {
- //获取摄像头矩阵
- jfloat *matrix = env->GetFloatArrayElements(matrix_,NULL);
- //加锁
- std::unique_lock lock(gMutex);
- //如果为空,就判断错误,中断
- if (!glCameraFilter){
- ALOGE("draw error, glCameraFilter is null");
- return;
- }
- //摄像头采集画图
- glCameraFilter->draw(matrix);
- //释放矩阵数据
- env->ReleaseFloatArrayElements(matrix_,matrix,0);
-}
-
-JNIEXPORT void JNICALL
-Java_com_cangwang_magic_util_OpenGLJniLib_magicFilterRelease(JNIEnv *env, jobject obj) {
- std::unique_lock lock(gMutex);
- if (glCameraFilter){
- glCameraFilter->stop();
- delete glCameraFilter;
- glCameraFilter = nullptr;
- }
-}
-
-//图片滤镜surfaceView初始化的时候创建
-JNIEXPORT jint JNICALL
-Java_com_cangwang_magic_util_OpenGLJniLib_magicImageFilterCreate(JNIEnv *env, jobject obj,
- jobject surface,jobject assetManager,jstring imgPath,jint degree) {
- std::unique_lock lock(gMutex);
- if(glImageFilter){ //停止摄像头采集并销毁
- glImageFilter->stop();
- delete glImageFilter;
- }
-
- //初始化native window
- ANativeWindow *window = ANativeWindow_fromSurface(env,surface);
- //初始化app内获取数据管理
- aAssetManager= AAssetManager_fromJava(env,assetManager);
- //初始化图片
- const char* addressStr = env->GetStringUTFChars(imgPath,0);
- std::string nativeAddress = addressStr;
-
- glImageFilter = new ImageFilter(window,aAssetManager,nativeAddress,degree);
- env->ReleaseStringUTFChars(imgPath, addressStr);
- //创建
- return glImageFilter->create();
-}
-
-//窗口大小设置,SurfaceView初始化后会触发一次
-JNIEXPORT void JNICALL
-Java_com_cangwang_magic_util_OpenGLJniLib_magicImageFilterChange(JNIEnv *env, jobject obj,jint width,jint height) {
- std::unique_lock lock(gMutex);
- //视口变换,可视区域
- if (!glImageFilter){
- ALOGE("change error, glImageFilter is null");
- return;
- }
- //更改窗口大小
- glImageFilter->change(width,height);
-}
-
-JNIEXPORT void JNICALL
-Java_com_cangwang_magic_util_OpenGLJniLib_magicImageFilterDraw(JNIEnv *env, jobject obj,jfloatArray matrix_,jstring address) {
- //获取摄像头矩阵
- jfloat *matrix = env->GetFloatArrayElements(matrix_,NULL);
- //加锁
- std::unique_lock lock(gMutex);
- //如果为空,就判断错误,中断
- if (!glImageFilter){
- ALOGE("draw error, glImageFilter is null");
- return;
- }
- //图片和滤镜绘制
- glImageFilter->draw(matrix);
- //释放矩阵数据
- env->ReleaseFloatArrayElements(matrix_,matrix,0);
-}
-
-JNIEXPORT void JNICALL
-Java_com_cangwang_magic_util_OpenGLJniLib_magicImageFilterRelease(JNIEnv *env, jobject obj) {
- std::unique_lock lock(gMutex);
- if (glImageFilter){
- glImageFilter->stop();
- delete glImageFilter;
- glImageFilter = nullptr;
- }
-}
-
-
-JNIEXPORT jintArray JNICALL
-Java_com_cangwang_magic_util_OpenGLJniLib_getFilterTypes(JNIEnv *env, jobject obj) {
- int len =0;
- jint* types = getFilterTypes(len);
- jintArray jin_arr=(env)->NewIntArray(len);
- (env)->SetIntArrayRegion(jin_arr,0,len,types);
- return jin_arr;
-}
-
-JNIEXPORT void JNICALL
-Java_com_cangwang_magic_util_OpenGLJniLib_setFilterType(JNIEnv *env, jobject obj,jint type) {
- if(glCameraFilter!= nullptr)
- glCameraFilter->setFilter(type);
- else ALOGE("filter set error, glCameraFilter is null");
-}
-
-JNIEXPORT void JNICALL
-Java_com_cangwang_magic_util_OpenGLJniLib_setImageFilterType(JNIEnv *env, jobject obj,jint type) {
- if(glImageFilter!= nullptr)
- glImageFilter->setFilter(type);
- else ALOGE("filter set error, glImageFilter is null");
-}
-
-JNIEXPORT void JNICALL
-Java_com_cangwang_magic_util_OpenGLJniLib_setImageBeautyLevel(JNIEnv *env, jobject obj,jint level) {
- if(glImageFilter!= nullptr)
- glImageFilter->setBeautyLevel(level);
- else ALOGE("beauty set error, glCameraFilter is null");
-}
-
-
-JNIEXPORT void JNICALL
-Java_com_cangwang_magic_util_OpenGLJniLib_setBeautyLevel(JNIEnv *env, jobject obj,jint level) {
- if(glCameraFilter!= nullptr)
- glCameraFilter->setBeautyLevel(level);
- else ALOGE("beauty set error, glCameraFilter is null");
-}
-
-JNIEXPORT jboolean JNICALL
-Java_com_cangwang_magic_util_OpenGLJniLib_savePhoto(JNIEnv *env, jobject obj,jstring address) {
- if (glCameraFilter != nullptr) {
- const char* addressStr = env->GetStringUTFChars(address,0);
- std::string nativeAddress = addressStr;
- bool result = false;
- if(glCameraFilter!= nullptr)
- result = glCameraFilter->savePhoto(nativeAddress);
- env->ReleaseStringUTFChars(address, addressStr);
- return static_cast(result);
- } else{
- ALOGE("save photo error, glCameraFilter is null");
- return static_cast(false);
- }
-}
-
-JNIEXPORT jboolean JNICALL
-Java_com_cangwang_magic_util_OpenGLJniLib_saveImage(JNIEnv *env, jobject obj,jstring address) {
- if (glImageFilter != nullptr) {
- const char* addressStr = env->GetStringUTFChars(address,0);
-
- std::string nativeAddress = addressStr;
- bool result = false;
- if(glImageFilter!= nullptr)
- result = glImageFilter->saveImage(nativeAddress);
- env->ReleaseStringUTFChars(address, addressStr);
- return static_cast(result);
- }else{
- ALOGE("save photo error, glImageFilter is null");
- return static_cast(false);
- }
-}
-
-}
diff --git a/app/src/main/java/com/cangwang/magic/BaseApplication.kt b/app/src/main/java/com/cangwang/magic/BaseApplication.kt
index 4e0dc0a..4418d63 100644
--- a/app/src/main/java/com/cangwang/magic/BaseApplication.kt
+++ b/app/src/main/java/com/cangwang/magic/BaseApplication.kt
@@ -3,14 +3,45 @@ package com.cangwang.magic
import android.annotation.SuppressLint
import android.app.Application
import android.content.Context
+import com.google.android.play.core.splitcompat.SplitCompat
+import com.google.android.play.core.splitinstall.SplitInstallManager
+import com.google.android.play.core.splitinstall.SplitInstallManagerFactory
+import com.google.android.play.core.splitinstall.SplitInstallRequest
class BaseApplication: Application() {
companion object {
@SuppressLint("StaticFieldLeak")
lateinit var context:Context
+
}
+ private var modulePlay:String=""
+
+ private lateinit var manager:SplitInstallManager
+
+ override fun attachBaseContext(base: Context?) {
+ super.attachBaseContext(base)
+ SplitCompat.install(base)
+ manager = SplitInstallManagerFactory.create(base)
+ modulePlay = base?.getString(R.string.module_feature_play)?:""
+ loadAndLaunchModule(modulePlay)
+ }
+
+ fun insatllAllFeaturesNow(){
+
+ }
+
+ fun loadAndLaunchModule(name:String){
+ if(manager.installedModules.contains(name)){
+
+ }
+
+ val request = SplitInstallRequest.newBuilder().addModule(name).build()
+ manager.startInstall(request)
+ }
+
+
override fun onCreate() {
super.onCreate()
context = applicationContext
diff --git a/app/src/main/java/com/cangwang/magic/CameraActivity.kt b/app/src/main/java/com/cangwang/magic/CameraActivity.kt
index 087d047..fb84769 100644
--- a/app/src/main/java/com/cangwang/magic/CameraActivity.kt
+++ b/app/src/main/java/com/cangwang/magic/CameraActivity.kt
@@ -9,43 +9,51 @@ import android.os.Bundle
import android.support.v4.app.ActivityCompat
import android.support.v4.content.PermissionChecker
import android.support.v7.app.AppCompatActivity
-import android.view.SurfaceHolder
-import android.view.View
-import android.view.Window
-import android.view.WindowManager
+import android.view.*
+import android.view.animation.Animation
+import android.view.animation.Transformation
+import android.widget.FrameLayout
import android.widget.RelativeLayout
+import com.cangwang.magic.camera.CameraTouch
import com.cangwang.magic.util.CameraHelper
import com.cangwang.magic.view.CameraSurfaceCallback
+import com.werb.pickphotoview.util.PickUtils
import kotlinx.android.synthetic.main.activity_camera.*
/**
* Created by cangwang on 2018/9/12.
*/
-class CameraActivity:AppCompatActivity(){
+class CameraActivity : AppCompatActivity() {
private val MODE_PIC = 1
private var CAMERA_PERMISSION_REQ = 1
- var mCamera: Camera?=null
+ var mCamera: Camera? = null
private val ASPECT_RATIO_ARRAY = floatArrayOf(9.0f / 16, 3.0f / 4)
var mAspectRatio = ASPECT_RATIO_ARRAY[0]
var mCameraId = Camera.CameraInfo.CAMERA_FACING_BACK
+ var surfaceCallback: CameraSurfaceCallback? = null
+ var mCameraTouch: CameraTouch? = null
+
+ private var mFoucesAnimation: FoucesAnimation? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN)
+ window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
+ WindowManager.LayoutParams.FLAG_FULLSCREEN)
requestWindowFeature(Window.FEATURE_NO_TITLE)
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
setContentView(R.layout.activity_camera)
- if (PermissionChecker.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_DENIED) run {
- ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA),CAMERA_PERMISSION_REQ)
- }else {
+ if (PermissionChecker.checkSelfPermission(this,
+ Manifest.permission.CAMERA) == PackageManager.PERMISSION_DENIED) run {
+ ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA),
+ CAMERA_PERMISSION_REQ)
+ } else {
initView()
}
}
-
- fun initView(){
+ private fun initView() {
btn_camera_filter.visibility = View.GONE
btn_camera_shutter.visibility = View.GONE
@@ -56,50 +64,159 @@ class CameraActivity:AppCompatActivity(){
btn_camera_mode.visibility = View.GONE
btn_camera_beauty.visibility = View.GONE
- val screenSize =Point()
+ val screenSize = Point()
windowManager.defaultDisplay.getSize(screenSize)
val params = glsurfaceview_camera.layoutParams as RelativeLayout.LayoutParams
- params.width= screenSize.x;
- params.height = screenSize.x* 16/9
+ params.width = screenSize.x;
+ params.height = screenSize.x * 16 / 9
glsurfaceview_camera.layoutParams = params
+ glsurfaceview_camera.setOnTouchListener(object : View.OnTouchListener {
+ var mClickOn = 0L
+ var mLastX = 0f
+ var mLastY = 0f
+ override fun onTouch(v: View?, event: MotionEvent?): Boolean {
+ when (event?.actionMasked) {
+ MotionEvent.ACTION_DOWN -> {
+ if (event.pointerCount == 1) {
+ mClickOn = System.currentTimeMillis()
+ mLastX = event.x
+ mLastY = event.y
+ }
+ }
+ MotionEvent.ACTION_UP -> {
+ if (event.pointerCount == 1 && System.currentTimeMillis() - mClickOn < 500) {
+ moveFocus(event.x.toInt(), event.y.toInt())
+ }
+ }
+ MotionEvent.ACTION_POINTER_DOWN -> {
+ mCameraTouch?.onScaleStart(event) {
+
+ }
+ return true
+ }
+ MotionEvent.ACTION_MOVE -> {
+ if (event.pointerCount == 2) {
+ mCameraTouch?.onScale(event)
+ return true
+ } else {
+ val x = event.x - mLastX
+ val y = event.y - mLastY
+ if (Math.abs(x) >= 10 || Math.abs(y) >= 10) {
+ mClickOn = 0L
+ }
+ }
+ }
+ MotionEvent.ACTION_POINTER_UP -> {
+ mCameraTouch?.onScaleEnd {
+
+ }
+ return true
+ }
+ }
+ return false
+ }
+ })
}
override fun onResume() {
super.onResume()
mCamera = openCamera(glsurfaceview_camera.holder)
- glsurfaceview_camera.holder.addCallback(CameraSurfaceCallback(mCamera))
+ surfaceCallback = CameraSurfaceCallback(mCamera)
+ glsurfaceview_camera.holder.addCallback(surfaceCallback)
}
override fun onPause() {
super.onPause()
mCamera?.stopPreview()
mCamera?.release()
+ glsurfaceview_camera.holder.removeCallback(surfaceCallback)
+ surfaceCallback?.releaseOpenGL()
+ surfaceCallback = null
}
- override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
- if (requestCode == CAMERA_PERMISSION_REQ &&(grantResults.size != 1 || grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
+ override fun onRequestPermissionsResult(
+ requestCode: Int, permissions: Array, grantResults: IntArray
+ ) {
+ if (requestCode == CAMERA_PERMISSION_REQ && (grantResults.size != 1 || grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
initView()
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
}
- fun openCamera(holder: SurfaceHolder?):Camera?{
- if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
+ private fun openCamera(holder: SurfaceHolder?): Camera? {
+ if (ActivityCompat.checkSelfPermission(this,
+ Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
return null
}
- if (mCamera!=null){
+ if (mCamera != null) {
return mCamera
}
mCamera = CameraHelper.openCamera(mCameraId)
mCamera?.let {
//这里android 相机长和宽默认偏移90度,所以传入要对调
- CameraHelper.setOptimalSize(it,mAspectRatio,CameraHelper.getScreenHeight(),CameraHelper.getScreenWidth())
- CameraHelper.setDisplayOritation(this,it,mCameraId)
+ CameraHelper.setOptimalSize(it, mAspectRatio, CameraHelper.getScreenHeight(),
+ CameraHelper.getScreenWidth())
+ CameraHelper.setDisplayOritation(this, it, mCameraId)
}
return mCamera
}
+ fun moveFocus(x: Int, y: Int) {
+ video_fouces.apply {
+ visibility = View.VISIBLE
+ val lp = video_fouces.layoutParams as RelativeLayout.LayoutParams
+ layoutParams = lp
+ mFoucesAnimation?.duration = 500
+ mFoucesAnimation?.repeatCount = 0
+ mFoucesAnimation?.setOldMargin(x, y)
+ video_fouces.startAnimation(mFoucesAnimation)
+ }
+ }
+
+ private fun removeImageFoucesRunnable() {
+ video_fouces.removeCallbacks(mImageFoucesRunnable)
+ }
+
+ private fun imageFoucesDelayedHind() {
+ video_fouces.postDelayed(mImageFoucesRunnable, 1000)
+ }
+
+ private val mImageFoucesRunnable = Runnable { video_fouces.visibility = View.GONE }
+
+ private inner class FoucesAnimation : Animation() {
+
+ private val width = PickUtils.dp2px(this@CameraActivity, 65f)
+ private val W = PickUtils.dp2px(this@CameraActivity, 65f)
+
+ private var oldMarginLeft: Int = 0
+ private var oldMarginTop: Int = 0
+
+ override fun applyTransformation(interpolatedTime: Float, t: Transformation) {
+
+ val layoutParams = video_fouces.layoutParams as FrameLayout.LayoutParams
+ var w = (width * (1 - interpolatedTime)).toInt()
+ if (w < W) {
+ w = W
+ }
+ layoutParams.width = w
+ layoutParams.height = w
+ if (w == W) {
+ video_fouces.layoutParams = layoutParams
+ return
+ }
+ layoutParams.leftMargin = oldMarginLeft - w / 2
+ layoutParams.topMargin = oldMarginTop + w / 8
+ video_fouces.layoutParams = layoutParams
+ }
+
+ fun setOldMargin(oldMarginLeft: Int, oldMarginTop: Int) {
+ this.oldMarginLeft = oldMarginLeft
+ this.oldMarginTop = oldMarginTop
+ removeImageFoucesRunnable()
+ imageFoucesDelayedHind()
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/cangwang/magic/CameraFilterActivity.kt b/app/src/main/java/com/cangwang/magic/CameraFilterActivity.kt
index 9055ceb..959dcf8 100644
--- a/app/src/main/java/com/cangwang/magic/CameraFilterActivity.kt
+++ b/app/src/main/java/com/cangwang/magic/CameraFilterActivity.kt
@@ -5,14 +5,11 @@ import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ObjectAnimator
import android.app.AlertDialog
-import android.content.DialogInterface
import android.content.pm.ActivityInfo
import android.content.pm.PackageManager
import android.graphics.Point
import android.hardware.Camera
-import android.os.Build
import android.os.Bundle
-import android.os.Environment
import android.support.v4.app.ActivityCompat
import android.support.v4.content.PermissionChecker
import android.support.v7.app.AppCompatActivity
@@ -22,9 +19,9 @@ import android.view.View
import android.view.Window
import android.view.WindowManager
import android.widget.RelativeLayout
+import com.cangwang.filter.util.OpenGLJniLib
import com.cangwang.magic.adapter.FilterAdapter
import com.cangwang.magic.util.CameraHelper
-import com.cangwang.magic.util.OpenGLJniLib
import com.cangwang.magic.view.CameraFilterSurfaceCallback
import kotlinx.android.synthetic.main.activity_camera.*
import kotlinx.android.synthetic.main.filter_layout.*
@@ -32,7 +29,7 @@ import kotlinx.android.synthetic.main.filter_layout.*
/**
* Created by cangwang on 2018/9/12.
*/
-class CameraFilterActivity:AppCompatActivity(){
+class CameraFilterActivity : AppCompatActivity() {
private var isRecording = false
private val MODE_PIC = 1
@@ -41,10 +38,10 @@ class CameraFilterActivity:AppCompatActivity(){
private var CAMERA_PERMISSION_REQ = 1
private var STORGE_PERMISSION_REQ = 2
private var mAdapter: FilterAdapter? = null
- private var mSurfaceCallback:CameraFilterSurfaceCallback?=null
- private var beautyLevel:Int = 0
+ private var mSurfaceCallback: CameraFilterSurfaceCallback? = null
+ private var beautyLevel: Int = 0
- var mCamera: Camera?=null
+ var mCamera: Camera? = null
private val ASPECT_RATIO_ARRAY = floatArrayOf(9.0f / 16, 3.0f / 4)
var mAspectRatio = ASPECT_RATIO_ARRAY[0]
@@ -53,21 +50,26 @@ class CameraFilterActivity:AppCompatActivity(){
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// window.setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED)
- window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN)
+ window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
+ WindowManager.LayoutParams.FLAG_FULLSCREEN)
requestWindowFeature(Window.FEATURE_NO_TITLE)
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
setContentView(R.layout.activity_camera)
- if (PermissionChecker.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_DENIED) run {
- ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA),CAMERA_PERMISSION_REQ)
- }else {
+ if (PermissionChecker.checkSelfPermission(this,
+ Manifest.permission.CAMERA) == PackageManager.PERMISSION_DENIED) run {
+ ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA),
+ CAMERA_PERMISSION_REQ)
+ } else {
initView()
}
- if (PermissionChecker.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) run {
- ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),STORGE_PERMISSION_REQ)
+ if (PermissionChecker.checkSelfPermission(this,
+ Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) run {
+ ActivityCompat.requestPermissions(this,
+ arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), STORGE_PERMISSION_REQ)
}
}
-// private val types = arrayOf(MagicFilterType.NONE, MagicFilterType.FAIRYTALE, MagicFilterType.SUNRISE,
+ // private val types = arrayOf(MagicFilterType.NONE, MagicFilterType.FAIRYTALE, MagicFilterType.SUNRISE,
// MagicFilterType.SUNSET, MagicFilterType.WHITECAT, MagicFilterType.BLACKCAT, MagicFilterType.SKINWHITEN, MagicFilterType.HEALTHY,
// MagicFilterType.SWEETS, MagicFilterType.ROMANCE, MagicFilterType.SAKURA, MagicFilterType.WARM, MagicFilterType.ANTIQUE,
// MagicFilterType.NOSTALGIA, MagicFilterType.CALM, MagicFilterType.LATTE, MagicFilterType.TENDER, MagicFilterType.COOL,
@@ -76,17 +78,18 @@ class CameraFilterActivity:AppCompatActivity(){
// MagicFilterType.INKWELL, MagicFilterType.KEVIN, MagicFilterType.LOMO, MagicFilterType.N1977, MagicFilterType.NASHVILLE,
// MagicFilterType.PIXAR, MagicFilterType.RISE, MagicFilterType.SIERRA, MagicFilterType.SUTRO, MagicFilterType.TOASTER2,
// MagicFilterType.VALENCIA, MagicFilterType.WALDEN, MagicFilterType.XPROII)
- private val types = OpenGLJniLib.getFilterTypes()
+ private val types = OpenGLJniLib.getFilterType()
- fun initView(){
- filter_listView.layoutManager = LinearLayoutManager(this,LinearLayoutManager.HORIZONTAL,false)
+ fun initView() {
+ filter_listView.layoutManager =
+ LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
mAdapter = FilterAdapter(this, types)
- mAdapter?.filterListener= object:FilterAdapter.onFilterChangeListener{
+ mAdapter?.filterListener = object : FilterAdapter.onFilterChangeListener {
override fun onFilterChanged(type: Int) {
mSurfaceCallback?.setFilterType(type)
}
}
- filter_listView.adapter= mAdapter
+ filter_listView.adapter = mAdapter
btn_camera_filter.setOnClickListener {
showFilters()
}
@@ -108,8 +111,8 @@ class CameraFilterActivity:AppCompatActivity(){
btn_camera_beauty.setOnClickListener {
AlertDialog.Builder(this)
- .setSingleChoiceItems(arrayOf("关闭", "1", "2", "3", "4", "5"), beautyLevel) {
- dialog, which ->
+ .setSingleChoiceItems(arrayOf("关闭", "1", "2", "3", "4", "5"),
+ beautyLevel) { dialog, which ->
beautyLevel = which
OpenGLJniLib.setBeautyLevel(which)
dialog.dismiss()
@@ -117,13 +120,12 @@ class CameraFilterActivity:AppCompatActivity(){
.setNegativeButton("取消", null)
.show()
}
- val screenSize =Point()
+ val screenSize = Point()
windowManager.defaultDisplay.getSize(screenSize)
val params = glsurfaceview_camera.layoutParams as RelativeLayout.LayoutParams
- params.width= screenSize.x
- params.height = screenSize.x* 16/9
+ params.width = screenSize.x
+ params.height = screenSize.x * 16 / 9
glsurfaceview_camera.layoutParams = params
-
}
override fun onResume() {
@@ -131,7 +133,7 @@ class CameraFilterActivity:AppCompatActivity(){
initCamera()
}
- private fun initCamera(){
+ private fun initCamera() {
releaseCamera()
mCamera = openCamera(glsurfaceview_camera.holder)
mSurfaceCallback = CameraFilterSurfaceCallback(mCamera)
@@ -148,7 +150,9 @@ class CameraFilterActivity:AppCompatActivity(){
super.onDestroy()
}
- override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
+ override fun onRequestPermissionsResult(
+ requestCode: Int, permissions: Array, grantResults: IntArray
+ ) {
// if (grantResults.size !=1 || grantResults[0] ==PackageManager.PERMISSION_GRANTED){
// if (mode == MODE_PIC){
// takePhoto()
@@ -157,7 +161,7 @@ class CameraFilterActivity:AppCompatActivity(){
// }
// }
// super.onRequestPermissionsResult(requestCode, permissions, grantResults)
- if (requestCode == CAMERA_PERMISSION_REQ &&(grantResults.size != 1 || grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
+ if (requestCode == CAMERA_PERMISSION_REQ && (grantResults.size != 1 || grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
initView()
initCamera()
} else {
@@ -165,43 +169,44 @@ class CameraFilterActivity:AppCompatActivity(){
}
}
- fun takePhoto(){
+ fun takePhoto() {
mSurfaceCallback?.takePhoto()
}
- fun takeVideo(){
-
+ fun takeVideo() {
}
- fun switchCamera(){
- mCameraId = if (mCameraId == Camera.CameraInfo.CAMERA_FACING_BACK ) Camera.CameraInfo.CAMERA_FACING_FRONT else Camera.CameraInfo.CAMERA_FACING_BACK
+ fun switchCamera() {
+ mCameraId =
+ if (mCameraId == Camera.CameraInfo.CAMERA_FACING_BACK) Camera.CameraInfo.CAMERA_FACING_FRONT else Camera.CameraInfo.CAMERA_FACING_BACK
releaseCamera()
mCamera = openCamera(glsurfaceview_camera.holder)
mSurfaceCallback?.changeCamera(mCamera)
}
- fun releaseCamera(){
+ fun releaseCamera() {
mCamera?.setPreviewCallback(null)
mCamera?.stopPreview()
mCamera?.release()
mCamera = null
}
-
- fun openCamera(holder: SurfaceHolder?):Camera?{
- if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
+ fun openCamera(holder: SurfaceHolder?): Camera? {
+ if (ActivityCompat.checkSelfPermission(this,
+ Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
return null
}
- if (mCamera!=null){
+ if (mCamera != null) {
return mCamera
}
mCamera = CameraHelper.openCamera(mCameraId)
mCamera?.let {
//这里android 相机长和宽默认偏移90度,所以传入要对调
- CameraHelper.setOptimalSize(it,mAspectRatio,CameraHelper.getScreenHeight(),CameraHelper.getScreenWidth())
- CameraHelper.setDisplayOritation(this,it,mCameraId)
+ CameraHelper.setOptimalSize(it, mAspectRatio, CameraHelper.getScreenHeight(),
+ CameraHelper.getScreenWidth())
+ CameraHelper.setDisplayOritation(this, it, mCameraId)
}
return mCamera
}
@@ -209,7 +214,7 @@ class CameraFilterActivity:AppCompatActivity(){
private fun showFilters() {
val animator = ObjectAnimator.ofInt(layout_filter, "translationY", layout_filter.height, 0)
animator.duration = 200
- animator.addListener(object :AnimatorListenerAdapter(){
+ animator.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationStart(animation: Animator) {
findViewById(R.id.btn_camera_shutter).isClickable = false
layout_filter.visibility = View.VISIBLE
@@ -222,7 +227,7 @@ class CameraFilterActivity:AppCompatActivity(){
private fun hideFilters() {
val animator = ObjectAnimator.ofInt(layout_filter, "translationY", 0, layout_filter.height)
animator.duration = 200
- animator.addListener(object :AnimatorListenerAdapter(){
+ animator.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
// TODO Auto-generated method stub
layout_filter.visibility = View.INVISIBLE
diff --git a/app/src/main/java/com/cangwang/magic/CameraFilterV2Activity.kt b/app/src/main/java/com/cangwang/magic/CameraFilterV2Activity.kt
index f0c0e31..23b202b 100644
--- a/app/src/main/java/com/cangwang/magic/CameraFilterV2Activity.kt
+++ b/app/src/main/java/com/cangwang/magic/CameraFilterV2Activity.kt
@@ -3,60 +3,80 @@ package com.cangwang.magic
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ObjectAnimator
+import android.animation.ValueAnimator
import android.app.AlertDialog
import android.content.pm.ActivityInfo
import android.graphics.Point
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.LinearLayoutManager
+import android.util.Log
import android.view.View
import android.view.Window
import android.view.WindowManager
import android.widget.RelativeLayout
import com.cangwang.magic.adapter.FilterAdapter
import com.cangwang.magic.camera.CameraCompat
-import com.cangwang.magic.util.OpenGLJniLib
-import com.cangwang.magic.view.CameraFilterSurfaceCallbackV2
+import com.cangwang.filter.util.OpenGLJniLib
+import com.cangwang.magic.view.CameraFilterSurfaceCallbackV3
+import io.reactivex.Observable
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.disposables.Disposable
import kotlinx.android.synthetic.main.activity_camera.*
import kotlinx.android.synthetic.main.filter_layout.*
+import java.util.concurrent.TimeUnit
/**
+ * 滤镜录制
* Created by cangwang on 2018/9/12.
*/
-class CameraFilterV2Activity:AppCompatActivity(){
-
- private var isRecording = false
+class CameraFilterV2Activity : AppCompatActivity() {
+ private val TAG = CameraFilterV2Activity::class.java.simpleName
private val MODE_PIC = 1
private val MODE_VIDEO = 2
private var mode = MODE_PIC
+ /**
+ * 视频最长的时长是15秒
+ */
+ private val VIDEO_MAX_TIME = 15
private var mAdapter: FilterAdapter? = null
- private var mSurfaceCallback:CameraFilterSurfaceCallbackV2?=null
- private var beautyLevel:Int = 0
+ private var mSurfaceCallback: CameraFilterSurfaceCallbackV3? = null
+ private var beautyLevel: Int = 0
+
+ var mCamera: CameraCompat? = null
+ var filterType: Int = 0
- var mCamera: CameraCompat?=null
+ private var videoAnimator: ObjectAnimator? = null
+ /**
+ * 录像倒计时终止器
+ */
+ private var mDisposable: Disposable? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// window.setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED)
- window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN)
+ window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
+ WindowManager.LayoutParams.FLAG_FULLSCREEN)
requestWindowFeature(Window.FEATURE_NO_TITLE)
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
setContentView(R.layout.activity_camera)
initView()
}
- private val types = OpenGLJniLib.getFilterTypes()
+ private val types = OpenGLJniLib.getFilterType()
- fun initView(){
- filter_listView.layoutManager = LinearLayoutManager(this,LinearLayoutManager.HORIZONTAL,false)
+ private fun initView() {
+ filter_listView.layoutManager =
+ LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
mAdapter = FilterAdapter(this, types)
- mAdapter?.filterListener= object:FilterAdapter.onFilterChangeListener{
- override fun onFilterChanged(type: Int) {
- mSurfaceCallback?.setFilterType(type)
+ mAdapter?.filterListener = object : FilterAdapter.onFilterChangeListener {
+ override fun onFilterChanged(filterType: Int) {
+ this@CameraFilterV2Activity.filterType = filterType
+ mSurfaceCallback?.setFilterType(filterType)
}
}
- filter_listView.adapter= mAdapter
+ filter_listView.adapter = mAdapter
btn_camera_filter.setOnClickListener {
showFilters()
}
@@ -65,7 +85,11 @@ class CameraFilterV2Activity:AppCompatActivity(){
}
btn_camera_shutter.setOnClickListener {
- takePhoto()
+ if (mode == MODE_PIC) {
+ takePhoto()
+ } else if (mode == MODE_VIDEO) {
+ takeVideo()
+ }
}
btn_camera_switch.setOnClickListener {
@@ -73,13 +97,19 @@ class CameraFilterV2Activity:AppCompatActivity(){
}
btn_camera_mode.setOnClickListener {
-
+ if (mode == MODE_PIC) {
+ mode = MODE_VIDEO
+ btn_camera_mode.setImageResource(R.drawable.icon_camera)
+ } else if (mode == MODE_VIDEO) {
+ mode = MODE_PIC
+ btn_camera_mode.setImageResource(R.drawable.icon_video)
+ }
}
btn_camera_beauty.setOnClickListener {
AlertDialog.Builder(this)
- .setSingleChoiceItems(arrayOf("关闭", "1", "2", "3", "4", "5"), beautyLevel) {
- dialog, which ->
+ .setSingleChoiceItems(arrayOf("关闭", "1", "2", "3", "4", "5"),
+ beautyLevel) { dialog, which ->
beautyLevel = which
OpenGLJniLib.setBeautyLevel(which)
dialog.dismiss()
@@ -87,48 +117,54 @@ class CameraFilterV2Activity:AppCompatActivity(){
.setNegativeButton("取消", null)
.show()
}
-// val screenSize =Point()
-// windowManager.defaultDisplay.getSize(screenSize)
-// val params = glsurfaceview_camera.layoutParams as RelativeLayout.LayoutParams
-// params.width= screenSize.x
-// params.height = screenSize.x* 16/9
-// glsurfaceview_camera.layoutParams = params
+ videoAnimator = ObjectAnimator.ofFloat(btn_camera_shutter, "rotation", 0f, 360f)
+ videoAnimator?.duration = 500
+ videoAnimator?.repeatCount = ValueAnimator.INFINITE
}
override fun onResume() {
super.onResume()
initCamera()
+ Log.d(TAG, "initCamera")
}
- private fun initCamera(){
+ private fun initCamera() {
mCamera = CameraCompat.newInstance(this)
- mSurfaceCallback = CameraFilterSurfaceCallbackV2(mCamera)
+ mSurfaceCallback = CameraFilterSurfaceCallbackV3(mCamera, filterType)
glsurfaceview_camera.holder.addCallback(mSurfaceCallback)
+ //初始化摄像头
mCamera?.startPreview()
}
override fun onPause() {
- mCamera?.stopPreview(false)
+ if (mSurfaceCallback?.isRecording() == true) {
+ releaseVideoRecord()
+ }
+// mCamera?.stopPreview(true)
+ glsurfaceview_camera.holder.removeCallback(mSurfaceCallback)
+ mSurfaceCallback?.releaseOpenGL()
+ mSurfaceCallback = null
+ mCamera = null
super.onPause()
}
- override fun onDestroy() {
- super.onDestroy()
- }
-
- fun takePhoto(){
+ private fun takePhoto() {
mSurfaceCallback?.takePhoto()
}
- fun takeVideo(){
-
+ private fun takeVideo() {
+ if (mSurfaceCallback?.isRecording() == true) {
+ releaseVideoRecord()
+ } else {
+ startVideoRecord()
+ }
}
private fun showFilters() {
val animator = ObjectAnimator.ofInt(layout_filter, "translationY", layout_filter.height, 0)
animator.duration = 200
- animator.addListener(object :AnimatorListenerAdapter(){
+ animator.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationStart(animation: Animator) {
btn_camera_shutter.isClickable = false
layout_filter.visibility = View.VISIBLE
@@ -141,7 +177,7 @@ class CameraFilterV2Activity:AppCompatActivity(){
private fun hideFilters() {
val animator = ObjectAnimator.ofInt(layout_filter, "translationY", 0, layout_filter.height)
animator.duration = 200
- animator.addListener(object :AnimatorListenerAdapter(){
+ animator.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
// TODO Auto-generated method stub
layout_filter.visibility = View.INVISIBLE
@@ -158,10 +194,78 @@ class CameraFilterV2Activity:AppCompatActivity(){
}
override fun onBackPressed() {
- if(layout_filter.visibility ==View.VISIBLE){
+ if (layout_filter.visibility == View.VISIBLE) {
hideFilters()
- }else {
+ } else {
super.onBackPressed()
}
}
+
+ private fun startVideoRecord() {
+ showVideoRecord()
+ mSurfaceCallback?.startRecordVideo()
+ videoAnimator?.start()
+ }
+
+ private fun releaseVideoRecord() {
+ mSurfaceCallback?.releaseRecordVideo()
+ videoAnimator?.end()
+ hideVideoRecord()
+ }
+
+ private fun showVideoRecord() {
+ video_record_seek_bar.visibility = View.VISIBLE
+ btn_camera_mode.visibility = View.GONE
+ btn_camera_switch.visibility = View.GONE
+ btn_camera_beauty.visibility = View.GONE
+ btn_camera_filter.visibility = View.GONE
+ cutPadding()
+ recordCountDown()
+ }
+
+ private fun hideVideoRecord() {
+ video_record_seek_bar.visibility = View.GONE
+ btn_camera_mode.visibility = View.VISIBLE
+ btn_camera_switch.visibility = View.VISIBLE
+ btn_camera_beauty.visibility = View.VISIBLE
+ btn_camera_filter.visibility = View.VISIBLE
+ stopRecordCountTime()
+ }
+
+ /**
+ * 重新设置录像的进度条样式
+ */
+ private fun cutPadding() {
+ val point = Point()
+ windowManager.defaultDisplay.getSize(point)
+ val width = point.x
+ val padding = video_record_seek_bar.paddingLeft
+ val layoutParams = video_record_seek_bar.layoutParams as RelativeLayout.LayoutParams
+ layoutParams.width = width + padding
+ video_record_seek_bar.layoutParams = layoutParams
+ video_record_seek_bar.setPadding(0, 0, 0, 0)
+ }
+
+ private fun recordCountDown() {
+ val count = 15
+ mDisposable = Observable.interval(1, 1, TimeUnit.SECONDS)
+ .take((count + 1).toLong())
+ .map { t ->
+ count - t
+ }
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe { aLong ->
+ val time = 16 - aLong!!
+
+ video_record_seek_bar.progress = time.toInt()
+ if (time == VIDEO_MAX_TIME.toLong()) {
+ releaseVideoRecord()
+ }
+ }
+ }
+
+ private fun stopRecordCountTime() {
+ mDisposable?.dispose()
+ mDisposable = null
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/cangwang/magic/CameraSampleActivity.kt b/app/src/main/java/com/cangwang/magic/CameraSampleActivity.kt
new file mode 100755
index 0000000..d605d3c
--- /dev/null
+++ b/app/src/main/java/com/cangwang/magic/CameraSampleActivity.kt
@@ -0,0 +1,154 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+package com.cangwang.magic
+
+import android.app.Activity
+import android.graphics.Bitmap
+import android.media.MediaScannerConnection
+import android.os.Bundle
+import android.os.Environment
+import android.view.View
+import android.widget.SeekBar
+import android.widget.Toast
+
+import com.cangwang.gpuimage.GPUImage
+import com.cangwang.gpuimage.GPUImageFilter
+import com.cangwang.gpuimage.GPUImageSource
+import com.cangwang.gpuimage.GPUImageSourceCamera
+import com.cangwang.gpuimage.GPUImageView
+import com.cangwang.magic.util.FilterHelper
+import kotlinx.android.synthetic.main.activity_camera_sample.*
+
+import java.io.File
+import java.io.FileNotFoundException
+import java.io.FileOutputStream
+
+class CameraSampleActivity : Activity(), View.OnClickListener, SeekBar.OnSeekBarChangeListener,
+ FilterHelper.OnFilterSelectedListener {
+
+ private var sourceCamera: GPUImageSourceCamera? = null
+ private var filter: GPUImageFilter? = null
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_camera_sample)
+
+ btn_flip_cam.setOnClickListener(this)
+ btn_filter.setOnClickListener(this)
+ btn_capture.setOnClickListener(this)
+
+ val seekBar = findViewById(R.id.seek) as SeekBar
+ seekBar.setOnSeekBarChangeListener(this)
+ seekBar.progress = 50
+
+ sourceCamera = GPUImageSourceCamera(this@CameraSampleActivity)
+ filter = GPUImageFilter.create("BrightnessFilter")
+ filter?.let {
+ sourceCamera?.addTarget(it)
+ ?.addTarget(findViewById(R.id.gpuimagexview) as GPUImageView)
+ }
+ sourceCamera?.let {
+ GPUImage.setSource(it)
+ }
+ }
+
+ override fun onClick(v: View) {
+ when (v.id) {
+ R.id.btn_flip_cam -> if (sourceCamera != null) {
+ sourceCamera!!.switchCamera()
+ }
+ R.id.btn_filter -> FilterHelper.showListDialog(this, this)
+ R.id.btn_capture -> sourceCamera?.captureAProcessedFrameData(filter,
+ object : GPUImageSource.ProcessedFrameDataCallback {
+ override fun onResult(result: Bitmap?) {
+ if (result != null) {
+ val path = Environment
+ .getExternalStoragePublicDirectory(
+ Environment.DIRECTORY_PICTURES)
+ val file = File(path,
+ "gpuimage-x" + "/" + System.currentTimeMillis() + ".jpg")
+ try {
+ file.parentFile.mkdirs()
+ result.compress(Bitmap.CompressFormat.JPEG, 80,
+ FileOutputStream(file))
+
+ // make a toast
+ runOnUiThread {
+ Toast.makeText(this@CameraSampleActivity,
+ "Image Saved:" + file.absolutePath,
+ Toast.LENGTH_SHORT).show()
+ }
+
+ // Tell the media scanner about the new file,
+ // so that it is immediately present in your album.
+ MediaScannerConnection.scanFile(this@CameraSampleActivity,
+ arrayOf(file.toString()), null, null)
+ } catch (e: FileNotFoundException) {
+ e.printStackTrace()
+ }
+ }
+ }
+ })
+ else -> {
+ }
+ }
+ }
+
+ override fun OnFilterSelected(newFilter: GPUImageFilter) {
+ filter?.let {
+ sourceCamera?.removeTarget(it)
+ it.destroy() // destroy instance if you want
+ }
+ sourceCamera?.addTarget(newFilter)
+ ?.addTarget(findViewById(R.id.gpuimagexview) as GPUImageView)
+ filter = newFilter
+ //sourceCamera.proceed();
+ }
+
+ override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
+ if (sourceCamera != null && filter != null) {
+ val value = progress / 100.0f // let the value between 0 and 1
+ FilterHelper.applyFilterWithSliderValue(filter!!, value)
+ //sourceCamera.proceed();
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ if (sourceCamera != null) {
+ sourceCamera!!.onResume()
+ }
+ }
+
+ override fun onPause() {
+ if (sourceCamera != null) {
+ sourceCamera!!.onPause()
+ }
+ super.onPause()
+ }
+
+ override fun onDestroy() {
+ GPUImage.destroy()
+ super.onDestroy()
+ }
+
+ override fun onStartTrackingTouch(seekBar: SeekBar) {}
+
+ override fun onStopTrackingTouch(seekBar: SeekBar) {}
+}
diff --git a/app/src/main/java/com/cangwang/magic/ImageEditActivity.kt b/app/src/main/java/com/cangwang/magic/ImageEditActivity.kt
index ce64ae0..671c0ae 100644
--- a/app/src/main/java/com/cangwang/magic/ImageEditActivity.kt
+++ b/app/src/main/java/com/cangwang/magic/ImageEditActivity.kt
@@ -12,7 +12,7 @@ import android.view.View
import android.view.Window
import android.view.WindowManager
import com.cangwang.magic.adapter.FilterAdapter
-import com.cangwang.magic.util.OpenGLJniLib
+import com.cangwang.filter.util.OpenGLJniLib
import com.cangwang.magic.view.ImageFilterSurfaceCallback
import com.werb.pickphotoview.model.SelectModel
import com.werb.pickphotoview.util.PickConfig
@@ -22,16 +22,18 @@ import kotlinx.android.synthetic.main.filter_layout.*
/**
* 图片编辑
*/
-class ImageEditActivity:AppCompatActivity(){
+class ImageEditActivity : AppCompatActivity() {
private var mAdapter: FilterAdapter? = null
- private var mSurfaceCallback: ImageFilterSurfaceCallback?=null
- private var beautyLevel:Int = 0
- private val types = OpenGLJniLib.getFilterTypes()
+ private var mSurfaceCallback: ImageFilterSurfaceCallback? = null
+ private var beautyLevel: Int = 0
+ private val types = OpenGLJniLib.getFilterType()
+ private var filterType = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN)
+ window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
+ WindowManager.LayoutParams.FLAG_FULLSCREEN)
requestWindowFeature(Window.FEATURE_NO_TITLE)
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
setContentView(R.layout.activity_album)
@@ -42,15 +44,17 @@ class ImageEditActivity:AppCompatActivity(){
super.onResume()
}
- private fun initView(){
- filter_listView.layoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL,false)
+ private fun initView() {
+ filter_listView.layoutManager =
+ LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
mAdapter = FilterAdapter(this, types)
- mAdapter?.filterListener= object: FilterAdapter.onFilterChangeListener{
+ mAdapter?.filterListener = object : FilterAdapter.onFilterChangeListener {
override fun onFilterChanged(type: Int) {
+ filterType = type
mSurfaceCallback?.setFilterType(type)
}
}
- filter_listView.adapter= mAdapter
+ filter_listView.adapter = mAdapter
initPreview()
btn_album_filter.setOnClickListener {
showFilters()
@@ -65,8 +69,8 @@ class ImageEditActivity:AppCompatActivity(){
btn_album_beauty.setOnClickListener {
AlertDialog.Builder(this)
- .setSingleChoiceItems(arrayOf("关闭", "1", "2", "3", "4", "5"), beautyLevel) {
- dialog, which ->
+ .setSingleChoiceItems(arrayOf("关闭", "1", "2", "3", "4", "5"),
+ beautyLevel) { dialog, which ->
beautyLevel = which
OpenGLJniLib.setImageBeautyLevel(which)
dialog.dismiss()
@@ -74,19 +78,26 @@ class ImageEditActivity:AppCompatActivity(){
.setNegativeButton("取消", null)
.show()
}
-
}
- private fun initPreview(){
- val selectPaths = intent.getSerializableExtra(PickConfig.INTENT_IMG_LIST_SELECT) as SelectModel
- mSurfaceCallback = ImageFilterSurfaceCallback(selectPaths.path)
+ private fun initPreview() {
+ val selectPaths =
+ intent.getSerializableExtra(PickConfig.INTENT_IMG_LIST_SELECT) as SelectModel
+ mSurfaceCallback = ImageFilterSurfaceCallback(selectPaths.path, filterType)
album_surfaceview.holder.addCallback(mSurfaceCallback)
}
+ override fun onDestroy() {
+ album_surfaceview.holder.removeCallback(mSurfaceCallback)
+ mSurfaceCallback?.releaseOpenGL()
+ mSurfaceCallback = null
+ super.onDestroy()
+ }
+
private fun showFilters() {
val animator = ObjectAnimator.ofInt(layout_filter, "translationY", layout_filter.height, 0)
animator.duration = 200
- animator.addListener(object :AnimatorListenerAdapter(){
+ animator.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationStart(animation: Animator) {
btn_album_save.isClickable = false
layout_filter.visibility = View.VISIBLE
@@ -99,7 +110,7 @@ class ImageEditActivity:AppCompatActivity(){
private fun hideFilters() {
val animator = ObjectAnimator.ofInt(layout_filter, "translationY", 0, layout_filter.height)
animator.duration = 200
- animator.addListener(object : AnimatorListenerAdapter(){
+ animator.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
// TODO Auto-generated method stub
layout_filter.visibility = View.INVISIBLE
diff --git a/app/src/main/java/com/cangwang/magic/MainActivity.kt b/app/src/main/java/com/cangwang/magic/MainActivity.kt
index 77e32e3..76768e6 100644
--- a/app/src/main/java/com/cangwang/magic/MainActivity.kt
+++ b/app/src/main/java/com/cangwang/magic/MainActivity.kt
@@ -12,53 +12,77 @@ import com.werb.pickphotoview.PickPhotoView
import com.werb.pickphotoview.model.SelectModel
import com.werb.pickphotoview.util.PickConfig
import kotlinx.android.synthetic.main.activity_main.*
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
import java.util.ArrayList
-class MainActivity : AppCompatActivity() {
+class MainActivity : AppCompatActivity(), CoroutineScope by CoroutineScope(Dispatchers.Default) {
companion object {
const val CAMERA_REQ = 1
const val CAMERA_FILTER = 2
+ const val ALBUM_REQ = 3
+ const val CAMERA_EFFECT = 4
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button_camera.setOnClickListener { v ->
- if (PermissionChecker.checkSelfPermission(this@MainActivity, Manifest.permission.CAMERA) == PackageManager.PERMISSION_DENIED) {
- ActivityCompat.requestPermissions(this@MainActivity, arrayOf(Manifest.permission.CAMERA), CAMERA_REQ)
+ if (PermissionChecker.checkSelfPermission(this@MainActivity,
+ Manifest.permission.CAMERA) == PackageManager.PERMISSION_DENIED) {
+ ActivityCompat.requestPermissions(this@MainActivity,
+ arrayOf(Manifest.permission.CAMERA), CAMERA_REQ)
} else {
startActivity(CAMERA_REQ)
}
}
button_filter.setOnClickListener {
- if (PermissionChecker.checkSelfPermission(this@MainActivity, Manifest.permission.CAMERA) == PackageManager.PERMISSION_DENIED ||
- PermissionChecker.checkSelfPermission(this@MainActivity, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) {
- ActivityCompat.requestPermissions(this@MainActivity, arrayOf(Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE), CAMERA_FILTER)
+ if (PermissionChecker.checkSelfPermission(this@MainActivity,
+ Manifest.permission.CAMERA) == PackageManager.PERMISSION_DENIED ||
+ PermissionChecker.checkSelfPermission(this@MainActivity,
+ Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED ||
+ PermissionChecker.checkSelfPermission(this@MainActivity,
+ Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_DENIED) {
+ ActivityCompat.requestPermissions(this@MainActivity,
+ arrayOf(Manifest.permission.CAMERA,
+ Manifest.permission.WRITE_EXTERNAL_STORAGE,
+ Manifest.permission.RECORD_AUDIO), CAMERA_FILTER)
} else {
startActivity(CAMERA_FILTER)
}
}
button_album.setOnClickListener {
- PickPhotoView.Builder(this@MainActivity)
- .setPickPhotoSize(1)
- .setClickSelectable(true) // click one image immediately close and return image
- .setShowCamera(true)
- .setHasPhotoSize(7)
- .setAllPhotoSize(10)
- .setSpanCount(3)
- .setLightStatusBar(false)
- .setShowGif(false) // is show gif
- .setShowVideo(false)
- .start()
+ if (PermissionChecker.checkSelfPermission(this@MainActivity,
+ Manifest.permission.CAMERA) == PackageManager.PERMISSION_DENIED) {
+ ActivityCompat.requestPermissions(this@MainActivity,
+ arrayOf(Manifest.permission.CAMERA), ALBUM_REQ)
+ } else {
+ startActivity(ALBUM_REQ)
+ }
+ }
+ button_effect.setOnClickListener {
+ if (PermissionChecker.checkSelfPermission(this@MainActivity,
+ Manifest.permission.CAMERA) == PackageManager.PERMISSION_DENIED) {
+ ActivityCompat.requestPermissions(this@MainActivity,
+ arrayOf(Manifest.permission.CAMERA), CAMERA_EFFECT)
+ } else {
+ startActivity(CAMERA_EFFECT)
+ }
}
}
- override fun onRequestPermissionsResult(requestCode: Int, permissions: Array,
- grantResults: IntArray) {
+ override fun onRequestPermissionsResult(
+ requestCode: Int, permissions: Array,
+ grantResults: IntArray
+ ) {
if (requestCode == CAMERA_REQ && grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
startActivity(CAMERA_REQ)
- }else if (requestCode == CAMERA_FILTER && grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED){
+ } else if (requestCode == CAMERA_FILTER && grantResults[0] == PackageManager.PERMISSION_GRANTED
+ && grantResults[1] == PackageManager.PERMISSION_GRANTED
+ && grantResults[2] == PackageManager.PERMISSION_GRANTED) {
startActivity(CAMERA_FILTER)
+ } else if (requestCode == ALBUM_REQ && grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ startActivity(ALBUM_REQ)
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
@@ -67,7 +91,22 @@ class MainActivity : AppCompatActivity() {
private fun startActivity(id: Int) {
when (id) {
CAMERA_REQ -> startActivity(Intent(this, CameraActivity::class.java))
- CAMERA_FILTER -> startActivity(Intent(this,CameraFilterV2Activity::class.java))
+ CAMERA_FILTER -> startActivity(Intent(this, CameraFilterV2Activity::class.java))
+ ALBUM_REQ -> {
+ PickPhotoView.Builder(this@MainActivity)
+ .setPickPhotoSize(1)
+ .setClickSelectable(
+ true) // click one image immediately close and return image
+ .setShowCamera(true)
+ .setHasPhotoSize(7)
+ .setAllPhotoSize(10)
+ .setSpanCount(3)
+ .setLightStatusBar(false)
+ .setShowGif(false) // is show gif
+ .setShowVideo(false)
+ .start()
+ }
+ CAMERA_EFFECT -> startActivity(Intent(this, CameraSampleActivity::class.java))
else -> {
}
}
@@ -82,13 +121,14 @@ class MainActivity : AppCompatActivity() {
return
}
if (requestCode == PickConfig.PICK_PHOTO_DATA) {
- val selectPaths = data.getSerializableExtra(PickConfig.INTENT_IMG_LIST_SELECT) as ArrayList
- if (selectPaths.size>0) {
+ val selectPaths = data.getSerializableExtra(
+ PickConfig.INTENT_IMG_LIST_SELECT) as ArrayList
+ if (selectPaths.size > 0) {
val intent = Intent(this, ImageEditActivity::class.java)
intent.putExtra(PickConfig.INTENT_IMG_LIST_SELECT, selectPaths[0])
startActivity(intent)
- }else{
- Toast.makeText(this,"choose no picture",Toast.LENGTH_SHORT).show()
+ } else {
+ Toast.makeText(this, "choose no picture", Toast.LENGTH_SHORT).show()
}
}
}
diff --git a/app/src/main/java/com/cangwang/magic/TriangleActivity.kt b/app/src/main/java/com/cangwang/magic/TriangleActivity.kt
index ef1b1fb..9204ce8 100644
--- a/app/src/main/java/com/cangwang/magic/TriangleActivity.kt
+++ b/app/src/main/java/com/cangwang/magic/TriangleActivity.kt
@@ -8,10 +8,10 @@ import com.cangwang.magic.util.RenderJNI
/**
* Created by zjl on 2018/10/12.
*/
-class TriangleActivity:AppCompatActivity(){
+class TriangleActivity : AppCompatActivity() {
- lateinit var mGLSurfaceView:GLSurfaceView
- lateinit var mRenderer:RenderJNI
+ lateinit var mGLSurfaceView: GLSurfaceView
+ lateinit var mRenderer: RenderJNI
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -32,6 +32,4 @@ class TriangleActivity:AppCompatActivity(){
super.onPause()
mGLSurfaceView.onPause()
}
-
-
}
\ No newline at end of file
diff --git a/app/src/main/java/com/cangwang/magic/adapter/FilterAdapter.kt b/app/src/main/java/com/cangwang/magic/adapter/FilterAdapter.kt
index 0287cbf..517f626 100644
--- a/app/src/main/java/com/cangwang/magic/adapter/FilterAdapter.kt
+++ b/app/src/main/java/com/cangwang/magic/adapter/FilterAdapter.kt
@@ -11,7 +11,6 @@ import android.widget.TextView
import com.cangwang.magic.R
import com.cangwang.magic.helper.FilterTypeHelper
-import com.cangwang.magic.helper.MagicFilterType
/**
* Created by why8222 on 2016/3/17.
diff --git a/app/src/main/java/com/cangwang/magic/camera/CameraCompat.kt b/app/src/main/java/com/cangwang/magic/camera/CameraCompat.kt
index 6b815f6..8fc62f6 100644
--- a/app/src/main/java/com/cangwang/magic/camera/CameraCompat.kt
+++ b/app/src/main/java/com/cangwang/magic/camera/CameraCompat.kt
@@ -6,7 +6,6 @@ import android.content.pm.PackageManager
import android.graphics.SurfaceTexture
import android.hardware.Camera
import android.os.Build
-import android.os.Looper
import android.support.annotation.IntDef
import android.util.Size
import android.util.SparseArray
@@ -85,7 +84,7 @@ abstract class CameraCompat(protected var mContext: Context) {
* 这里会两次调用此函数,第一次会初始化走openCamera,
* 第二次调用才能正常开始预览
*/
- fun startPreview() {
+ fun startPreview(callBack: CameraStateCallBack?=null) {
// if (Looper.myLooper() != Looper.getMainLooper()) {
// throw RuntimeException("you must start camera preview in main thread")
// }
@@ -103,10 +102,10 @@ abstract class CameraCompat(protected var mContext: Context) {
return
}
mStarted = true
- onStartPreview()
+ onStartPreview(callBack)
}
- protected abstract fun onStartPreview()
+ protected abstract fun onStartPreview(callBack: CameraStateCallBack?=null)
fun stopPreview(releaseSurface: Boolean) {
if (!mStarted) {
@@ -115,6 +114,7 @@ abstract class CameraCompat(protected var mContext: Context) {
mCameraReady = false
mStarted = false
if (releaseSurface) {
+ mSurfaceTexture?.release()
mSurfaceTexture = null
}
onStopPreview()
@@ -152,6 +152,22 @@ abstract class CameraCompat(protected var mContext: Context) {
mSwitchFlag = false
}
+ fun getCameraType():Int{
+ return if (mCameraType == FRONT_CAMERA) BACK_CAMERA else FRONT_CAMERA
+ }
+
+ open fun getMaxZoom():Float{
+ return 0f
+ }
+
+ open fun cameraZoom(scale:Float){
+
+ }
+
+ open fun requestFocus(x:Int,y:Int){
+
+ }
+
class CameraSize {
var width: Int = 0
var height: Int = 0
@@ -187,4 +203,8 @@ abstract class CameraCompat(protected var mContext: Context) {
}
}
+ interface CameraStateCallBack{
+ fun onConfigured()
+ fun onConfigureFailed()
+ }
}
diff --git a/app/src/main/java/com/cangwang/magic/camera/CameraCompatV19.kt b/app/src/main/java/com/cangwang/magic/camera/CameraCompatV19.kt
index 8097e46..ab73540 100644
--- a/app/src/main/java/com/cangwang/magic/camera/CameraCompatV19.kt
+++ b/app/src/main/java/com/cangwang/magic/camera/CameraCompatV19.kt
@@ -24,12 +24,14 @@ class CameraCompatV19(context: Context) : CameraCompat(context) {
}
}
- override fun onStartPreview() {
+ override fun onStartPreview(callBack: CameraStateCallBack?) {
try {
mCamera?.setPreviewTexture(mSurfaceTexture)
mCamera?.startPreview()
+ callBack?.onConfigured()
} catch (e: Throwable) {
Log.e(TAG, e.toString())
+ callBack?.onConfigureFailed()
}
}
diff --git a/app/src/main/java/com/cangwang/magic/camera/CameraCompatV21.kt b/app/src/main/java/com/cangwang/magic/camera/CameraCompatV21.kt
index 241cfca..187bac1 100644
--- a/app/src/main/java/com/cangwang/magic/camera/CameraCompatV21.kt
+++ b/app/src/main/java/com/cangwang/magic/camera/CameraCompatV21.kt
@@ -3,12 +3,14 @@ package com.cangwang.magic.camera
import android.annotation.SuppressLint
import android.annotation.TargetApi
import android.content.Context
+import android.graphics.Rect
import android.graphics.SurfaceTexture
import android.hardware.camera2.*
import android.os.Handler
import android.os.HandlerThread
import android.util.Log
import android.view.Surface
+import java.lang.Exception
@TargetApi(21)
@@ -27,6 +29,17 @@ class CameraCompatV21(context: Context) : CameraCompat(context) {
private var mSurface: Surface? = null
private var mBackgroundHandler: Handler? =null
private var mBackgroundThread:HandlerThread? =null
+ private var maxZoom = 0f
+
+ /**
+ * 放大的矩阵,拍照使用
+ */
+ private var mZoomRect: Rect? = null
+
+ /**
+ * 可缩放区域
+ */
+ private var mZoomSize: CameraCompat.CameraSize? = null
private val mCaptureStateCallback = object : CameraCaptureSession.StateCallback() {
override fun onConfigured(session: CameraCaptureSession) {
@@ -103,6 +116,7 @@ class CameraCompatV21(context: Context) : CameraCompat(context) {
//获取支持尺寸
val sizes = map.getOutputSizes(SurfaceTexture::class.java)
outputSize = CameraUtil.getLargePreviewSize(sizes)
+ mZoomSize = outputSize
} catch (e: CameraAccessException) {
Log.e(TAG, e.toString())
}
@@ -112,7 +126,7 @@ class CameraCompatV21(context: Context) : CameraCompat(context) {
private fun startRequest(session: CameraCaptureSession?) {
try {
- session?.setRepeatingRequest(mRequestBuilder?.build(), null, null)
+ session?.setRepeatingRequest(mRequestBuilder?.build(), null, mBackgroundHandler)
} catch (e: Throwable) {
Log.e(TAG, "", e)
}
@@ -129,9 +143,12 @@ class CameraCompatV21(context: Context) : CameraCompat(context) {
}
- override fun onStartPreview() {
+ override fun onStartPreview(callBack: CameraStateCallBack?) {
try {
+ mCaptureSession?.close()
+
mSurface = Surface(mSurfaceTexture)
+
outputSize?.let {
mSurfaceTexture?.setDefaultBufferSize(it.width, it.height)
}
@@ -139,6 +156,8 @@ class CameraCompatV21(context: Context) : CameraCompat(context) {
mRequestBuilder = mCamera?.createCaptureRequest(CameraDevice.TEMPLATE_RECORD)
mSurface?.let {
mRequestBuilder?.addTarget(it)
+ if (mZoomRect != null)
+ mRequestBuilder?.set(CaptureRequest.SCALER_CROP_REGION, mZoomRect) //放大的矩阵
mRequestBuilder?.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_VIDEO)
mRequestBuilder?.set(CaptureRequest.FLASH_MODE, if (mIsFlashLightOn)
@@ -147,7 +166,21 @@ class CameraCompatV21(context: Context) : CameraCompat(context) {
CaptureRequest.FLASH_MODE_OFF)
mCamera?.createCaptureSession(listOf(it),
- mCaptureStateCallback, mBackgroundHandler)
+ object : CameraCaptureSession.StateCallback() {
+ override fun onConfigured(session: CameraCaptureSession) {
+ if (mCamera == null) {
+ return
+ }
+ mCaptureSession = session
+ startRequest(session)
+ callBack?.onConfigured()
+ }
+
+ override fun onConfigureFailed(session: CameraCaptureSession) {
+ Log.e(TAG, "onConfigureFailed")
+ callBack?.onConfigureFailed()
+ }
+ }, mBackgroundHandler)
}
} catch (e: Throwable) {
@@ -157,6 +190,7 @@ class CameraCompatV21(context: Context) : CameraCompat(context) {
}
override fun onStopPreview() {
+ mSurface?.release()
abortSession()
mCamera?.close()
mCamera = null
@@ -187,21 +221,53 @@ class CameraCompatV21(context: Context) : CameraCompat(context) {
}catch (e:InterruptedException){
Log.e(TAG,e.toString())
}
+ }
+
+ override fun getMaxZoom():Float{
+ return maxZoom
+ }
+ override fun cameraZoom(sc:Float){
+ val scale = if(sc < 1.0f) 1.0f
+ else sc
+ if (scale <= maxZoom) {
+ mZoomSize?.apply {
+ val cropW = (width / (maxZoom * 2.6) * scale).toInt()
+ val cropH = (height / (maxZoom * 2.6) * scale).toInt()
+
+ val zoom = Rect(cropW, cropH,
+ width - cropW,
+ height - cropH)
+ mRequestBuilder?.set(CaptureRequest.SCALER_CROP_REGION, zoom)
+ mZoomRect = zoom
+ updatePreview() //重复更新预览请求
+ }
+ }
}
+ fun updatePreview(){
+ if (mCamera!=null){
+ try {
+ mCaptureSession?.setRepeatingRequest(mRequestBuilder?.build(),null,mBackgroundHandler)
+ }catch (e:Exception){
+ Log.e(TAG,e.toString())
+ }
+ }
+ }
@SuppressLint("MissingPermission")
private fun initialize(@CameraType cameraType: Int) {
try {
startBackgroundThread()
- //打开摄像头
- mManager?.openCamera(if (cameraType == FRONT_CAMERA)
+ val id = if (cameraType == FRONT_CAMERA)
frontCameraIdV21
else
- backCameraIdV21,
- mStateCallback, mBackgroundHandler)
+ backCameraIdV21
+ //打开摄像头
+ mManager?.openCamera(id, mStateCallback, mBackgroundHandler)
updateOutputSize()
+ val mCharacteristics = mManager?.getCameraCharacteristics(id)
+ maxZoom = mCharacteristics?.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM)?:0f
} catch (e: Throwable) {
Log.e(TAG, "", e)
}
@@ -224,6 +290,19 @@ class CameraCompatV21(context: Context) : CameraCompat(context) {
startRequest(mCaptureSession)
}
+ override fun requestFocus(x: Int, y: Int) {
+
+ }
+
+ fun calcTapAreaForCamera2(areaSize:Int,widght:Int,x:Float,y:Float){
+
+ }
+
+ fun clamp(modes:IntArray,mode:Int):Boolean{
+ modes.forEach { if (it == mode) return true }
+ return false
+ }
+
companion object {
private val TAG = "CameraCompatV21"
diff --git a/app/src/main/java/com/cangwang/magic/camera/CameraInfo.kt b/app/src/main/java/com/cangwang/magic/camera/CameraInfo.kt
index 10fa0ac..9977c20 100644
--- a/app/src/main/java/com/cangwang/magic/camera/CameraInfo.kt
+++ b/app/src/main/java/com/cangwang/magic/camera/CameraInfo.kt
@@ -1,3 +1,6 @@
package com.cangwang.magic.camera
-data class CameraInfo(var previewWidth:Int,var previewHeight:Int,var orientation:Int,var isFront:Boolean,var pictureWidth:Int,var pictureHeight:Int)
\ No newline at end of file
+data class CameraInfo(
+ var previewWidth: Int, var previewHeight: Int, var orientation: Int, var isFront: Boolean,
+ var pictureWidth: Int, var pictureHeight: Int
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/cangwang/magic/camera/CameraTouch.kt b/app/src/main/java/com/cangwang/magic/camera/CameraTouch.kt
new file mode 100644
index 0000000..9262f59
--- /dev/null
+++ b/app/src/main/java/com/cangwang/magic/camera/CameraTouch.kt
@@ -0,0 +1,76 @@
+package com.cangwang.magic.camera
+
+import android.util.Log
+import android.view.MotionEvent
+
+class CameraTouch(cameraCompat: CameraCompat) {
+ var mOldScale = 1.0f
+ var mScale = 0f
+ var mSpan = 0f
+ var mOldSpan = 0f
+ var mFirstDistance = 0f
+ var cameraCompat: CameraCompat? = null
+
+ init {
+ this.cameraCompat = cameraCompat
+ }
+
+ fun onScale(event: MotionEvent) {
+ if (event.pointerCount == 2) {
+
+ val distance = distance(event)
+ if (mFirstDistance == 0f) {
+ mFirstDistance = distance
+ }
+ var scale = 0f
+ when {
+ distance > mFirstDistance -> {
+ scale = (distance - mFirstDistance) / 80
+ scale += mSpan
+ mOldSpan = scale
+ mScale = scale
+ }
+ distance < mFirstDistance -> {
+ scale = distance / mFirstDistance
+ mOldSpan = scale
+ mScale = scale.times(mOldScale)
+ }
+ else -> return
+ }
+ }
+ }
+
+ fun onScaleStart(event: MotionEvent, callback: (maxZoom: Float) -> Unit) {
+ mFirstDistance = 0f
+ callback(cameraCompat?.getMaxZoom() ?: 0f)
+ }
+
+ fun onScaleEnd(callback: ((maxZoom: Float) -> Unit)?) {
+ mOldScale = when {
+ mScale < 1.0f -> 1.0f
+ mScale > cameraCompat?.getMaxZoom() ?: 0f -> cameraCompat?.getMaxZoom() ?: 0f
+ else -> mScale
+ }
+ mSpan = mOldSpan
+ callback?.invoke(mOldScale)
+ Log.e("scale", "scale:end")
+ }
+
+ fun resetScale() {
+ mOldScale = 1.0f
+ mSpan = 0f
+ mFirstDistance = 0f
+ }
+
+ fun setScale(scale: Float) {
+ mScale = scale
+ mOldScale = scale
+ onScaleEnd(null)
+ }
+
+ private fun distance(event: MotionEvent): Float {
+ val dx = event.getX(1) - event.getX(0)
+ val dy = event.getY(1) - event.getY(0)
+ return Math.sqrt(dx.times(dx).toDouble() + dy.times(dy).toDouble()).toFloat()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/cangwang/magic/helper/FilterTypeHelper.java b/app/src/main/java/com/cangwang/magic/helper/FilterTypeHelper.java
index 10a0363..90e2f08 100644
--- a/app/src/main/java/com/cangwang/magic/helper/FilterTypeHelper.java
+++ b/app/src/main/java/com/cangwang/magic/helper/FilterTypeHelper.java
@@ -68,92 +68,106 @@ public static int FilterType2Color(int type){
public static int FilterType2Thumb(int type){
MagicFilterType filterType = MagicFilterType.values()[type];
switch (filterType) {
- case NONE:
- return R.drawable.filter_thumb_original;
- case WHITECAT:
- return R.drawable.filter_thumb_whitecat;
- case BLACKCAT:
- return R.drawable.filter_thumb_blackcat;
- case ROMANCE:
- return R.drawable.filter_thumb_romance;
- case SAKURA:
- return R.drawable.filter_thumb_sakura;
- case AMARO:
- return R.drawable.filter_thumb_amoro;
- case BRANNAN:
- return R.drawable.filter_thumb_brannan;
- case BROOKLYN:
- return R.drawable.filter_thumb_brooklyn;
- case EARLYBIRD:
- return R.drawable.filter_thumb_earlybird;
- case FREUD:
- return R.drawable.filter_thumb_freud;
- case HEFE:
- return R.drawable.filter_thumb_hefe;
- case HUDSON:
- return R.drawable.filter_thumb_hudson;
- case INKWELL:
- return R.drawable.filter_thumb_inkwell;
- case KEVIN:
- return R.drawable.filter_thumb_kevin;
- case LOMO:
- return R.drawable.filter_thumb_lomo;
- case N1977:
- return R.drawable.filter_thumb_1977;
- case NASHVILLE:
- return R.drawable.filter_thumb_nashville;
- case PIXAR:
- return R.drawable.filter_thumb_piaxr;
- case RISE:
- return R.drawable.filter_thumb_rise;
- case SIERRA:
- return R.drawable.filter_thumb_sierra;
- case SUTRO:
- return R.drawable.filter_thumb_sutro;
- case TOASTER2:
- return R.drawable.filter_thumb_toastero;
- case VALENCIA:
- return R.drawable.filter_thumb_valencia;
- case WALDEN:
- return R.drawable.filter_thumb_walden;
- case XPROII:
- return R.drawable.filter_thumb_xpro;
- case ANTIQUE:
- return R.drawable.filter_thumb_antique;
- case SKINWHITEN:
- return R.drawable.filter_thumb_beauty;
- case CALM:
- return R.drawable.filter_thumb_calm;
- case COOL:
- return R.drawable.filter_thumb_cool;
- case EMERALD:
- return R.drawable.filter_thumb_emerald;
- case EVERGREEN:
- return R.drawable.filter_thumb_evergreen;
- case FAIRYTALE:
- return R.drawable.filter_thumb_fairytale;
- case HEALTHY:
- return R.drawable.filter_thumb_healthy;
- case NOSTALGIA:
- return R.drawable.filter_thumb_nostalgia;
- case TENDER:
- return R.drawable.filter_thumb_tender;
- case SWEETS:
- return R.drawable.filter_thumb_sweets;
- case LATTE:
- return R.drawable.filter_thumb_latte;
- case WARM:
- return R.drawable.filter_thumb_warm;
- case SUNRISE:
- return R.drawable.filter_thumb_sunrise;
- case SUNSET:
- return R.drawable.filter_thumb_sunset;
- case CRAYON:
- return R.drawable.filter_thumb_crayon;
- case SKETCH:
- return R.drawable.filter_thumb_sketch;
- default:
- return R.drawable.filter_thumb_original;
+ case NONE:
+ return R.drawable.filter_thumb_original;
+ case SOULOUT:
+ return R.drawable.soulout;
+ case SHAKE:
+ return R.drawable.shade;
+ case SHINEWHITE:
+ return R.drawable.shinewhite;
+ case SCALE:
+ return R.drawable.scale;
+ case GLITCH:
+ return R.drawable.glitch;
+ case VERIGO:
+ return R.drawable.verigo;
+ case THREEWIN:
+ return R.drawable.soulout;
+ case WHITECAT:
+ return R.drawable.filter_thumb_whitecat;
+ case BLACKCAT:
+ return R.drawable.filter_thumb_blackcat;
+ case ROMANCE:
+ return R.drawable.filter_thumb_romance;
+ case SAKURA:
+ return R.drawable.filter_thumb_sakura;
+ case AMARO:
+ return R.drawable.filter_thumb_amoro;
+ case BRANNAN:
+ return R.drawable.filter_thumb_brannan;
+ case BROOKLYN:
+ return R.drawable.filter_thumb_brooklyn;
+ case EARLYBIRD:
+ return R.drawable.filter_thumb_earlybird;
+ case FREUD:
+ return R.drawable.filter_thumb_freud;
+ case HEFE:
+ return R.drawable.filter_thumb_hefe;
+ case HUDSON:
+ return R.drawable.filter_thumb_hudson;
+ case INKWELL:
+ return R.drawable.filter_thumb_inkwell;
+ case KEVIN:
+ return R.drawable.filter_thumb_kevin;
+ case LOMO:
+ return R.drawable.filter_thumb_lomo;
+ case N1977:
+ return R.drawable.filter_thumb_1977;
+ case NASHVILLE:
+ return R.drawable.filter_thumb_nashville;
+ case PIXAR:
+ return R.drawable.filter_thumb_piaxr;
+ case RISE:
+ return R.drawable.filter_thumb_rise;
+ case SIERRA:
+ return R.drawable.filter_thumb_sierra;
+ case SUTRO:
+ return R.drawable.filter_thumb_sutro;
+ case TOASTER2:
+ return R.drawable.filter_thumb_toastero;
+ case VALENCIA:
+ return R.drawable.filter_thumb_valencia;
+ case WALDEN:
+ return R.drawable.filter_thumb_walden;
+ case XPROII:
+ return R.drawable.filter_thumb_xpro;
+ case ANTIQUE:
+ return R.drawable.filter_thumb_antique;
+ case SKINWHITEN:
+ return R.drawable.filter_thumb_beauty;
+ case CALM:
+ return R.drawable.filter_thumb_calm;
+ case COOL:
+ return R.drawable.filter_thumb_cool;
+ case EMERALD:
+ return R.drawable.filter_thumb_emerald;
+ case EVERGREEN:
+ return R.drawable.filter_thumb_evergreen;
+ case FAIRYTALE:
+ return R.drawable.filter_thumb_fairytale;
+ case HEALTHY:
+ return R.drawable.filter_thumb_healthy;
+ case NOSTALGIA:
+ return R.drawable.filter_thumb_nostalgia;
+ case TENDER:
+ return R.drawable.filter_thumb_tender;
+ case SWEETS:
+ return R.drawable.filter_thumb_sweets;
+ case LATTE:
+ return R.drawable.filter_thumb_latte;
+ case WARM:
+ return R.drawable.filter_thumb_warm;
+ case SUNRISE:
+ return R.drawable.filter_thumb_sunrise;
+ case SUNSET:
+ return R.drawable.filter_thumb_sunset;
+ case CRAYON:
+ return R.drawable.filter_thumb_crayon;
+ case SKETCH:
+ return R.drawable.filter_thumb_sketch;
+ default:
+ return R.drawable.filter_thumb_original;
}
}
@@ -174,6 +188,8 @@ public static int FilterType2Name(int type){
return R.string.filter_glitch;
case VERIGO:
return R.string.filter_verigo;
+ case THREEWIN:
+ return R.string.filter_three_win;
case WHITECAT:
return R.string.filter_whitecat;
case BLACKCAT:
diff --git a/app/src/main/java/com/cangwang/magic/helper/MagicFilterType.java b/app/src/main/java/com/cangwang/magic/helper/MagicFilterType.java
index ee1e7ab..c25ac4e 100644
--- a/app/src/main/java/com/cangwang/magic/helper/MagicFilterType.java
+++ b/app/src/main/java/com/cangwang/magic/helper/MagicFilterType.java
@@ -11,6 +11,7 @@ public enum MagicFilterType {
SCALE,
SHINEWHITE,
VERIGO,
+ THREEWIN,
FAIRYTALE,
SUNRISE,
SUNSET,
diff --git a/app/src/main/java/com/cangwang/magic/util/CameraHelper.kt b/app/src/main/java/com/cangwang/magic/util/CameraHelper.kt
index 24e3a31..32b5a60 100644
--- a/app/src/main/java/com/cangwang/magic/util/CameraHelper.kt
+++ b/app/src/main/java/com/cangwang/magic/util/CameraHelper.kt
@@ -9,28 +9,28 @@ import com.cangwang.magic.BaseApplication
import com.cangwang.magic.camera.CameraInfo
import java.util.*
-
-object CameraHelper{
+object CameraHelper {
val TAG = CameraHelper::class.java.simpleName
- val cameraId= Camera.CameraInfo.CAMERA_FACING_BACK
+ val cameraId = Camera.CameraInfo.CAMERA_FACING_BACK
fun openCamera(): Camera? {
return openCamera(cameraId)
}
- fun openCamera(cameraId:Int):Camera?{
- if (!haveFeature(PackageManager.FEATURE_CAMERA)){
- Log.e(TAG,"no camera!")
+ fun openCamera(cameraId: Int): Camera? {
+ if (!haveFeature(PackageManager.FEATURE_CAMERA)) {
+ Log.e(TAG, "no camera!")
return null
}
- if (cameraId == Camera.CameraInfo.CAMERA_FACING_FRONT && !haveFeature(PackageManager.FEATURE_CAMERA_FRONT)){
- Log.e(TAG,"no front camera!")
+ if (cameraId == Camera.CameraInfo.CAMERA_FACING_FRONT && !haveFeature(
+ PackageManager.FEATURE_CAMERA_FRONT)) {
+ Log.e(TAG, "no front camera!")
return null
}
val camera = Camera.open(cameraId)
- if (camera == null){
+ if (camera == null) {
Log.e(TAG, "openCamera failed")
return null
}
@@ -39,14 +39,14 @@ object CameraHelper{
}
private fun haveFeature(name: String): Boolean {
- return BaseApplication.context.packageManager?.hasSystemFeature(name)?:false
+ return BaseApplication.context.packageManager?.hasSystemFeature(name) ?: false
}
/**
* 图片预览大小
*/
- fun setOptimalSize(camera:Camera,aspectRatio:Float,maxWidth:Int,maxHeight:Int){
- val parameters= camera.parameters
+ fun setOptimalSize(camera: Camera, aspectRatio: Float, maxWidth: Int, maxHeight: Int) {
+ val parameters = camera.parameters
//使用自动对焦
if (parameters.supportedFocusModes.contains(
Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
@@ -55,7 +55,7 @@ object CameraHelper{
val size = getLargePreviewSize(camera)
size?.let {
//设置相机预览大小
- parameters.setPreviewSize(it.width,it.height)
+ parameters.setPreviewSize(it.width, it.height)
Log.d(TAG, "input max: (" + maxWidth + ", " + maxHeight + "), output size: ("
+ it.width + ", " + it.height + ")")
}
@@ -63,7 +63,7 @@ object CameraHelper{
val pictureSize = getLargePictureSize(camera)
pictureSize?.let {
//图片参数
- parameters.setPictureSize(it.width,it.height)
+ parameters.setPictureSize(it.width, it.height)
Log.d(TAG, "picture max: (" + maxWidth + ", " + maxHeight + "), output size: ("
+ it.width + ", " + it.height + ")")
}
@@ -71,8 +71,10 @@ object CameraHelper{
camera.parameters = parameters
}
- fun chooseOptimalSize(options: List, aspectRatio: Float,
- maxWidth: Int, maxHeight: Int): Camera.Size {
+ fun chooseOptimalSize(
+ options: List, aspectRatio: Float,
+ maxWidth: Int, maxHeight: Int
+ ): Camera.Size {
val alternative = ArrayList()
for (option in options) {
if (option.height.toFloat() == option.width * aspectRatio && option.width <= maxWidth
@@ -84,16 +86,15 @@ object CameraHelper{
return if (alternative.size > 0) {
Collections.max(alternative, CompareSizesByArea())
} else options[0]
-
}
private class CompareSizesByArea : Comparator {
override fun compare(lhs: Camera.Size, rhs: Camera.Size): Int {
// 转型 long 是为了确保乘法运算不会溢出
- return java.lang.Long.signum(lhs.width.toLong() * lhs.height - rhs.width.toLong() * rhs.height)
+ return java.lang.Long.signum(
+ lhs.width.toLong() * lhs.height - rhs.width.toLong() * rhs.height)
}
-
}
fun setDisplayOritation(activity: Activity, camera: Camera, cameraId: Int) {
@@ -121,12 +122,12 @@ object CameraHelper{
fun getScreenWidth(): Int {
val metrics = BaseApplication.context.resources?.displayMetrics
- return metrics?.widthPixels?:0
+ return metrics?.widthPixels ?: 0
}
fun getScreenHeight(): Int {
val metrics = BaseApplication.context.resources?.displayMetrics
- return metrics?.heightPixels?:0
+ return metrics?.heightPixels ?: 0
}
fun setFocusMode(camera: Camera, focusMode: String) {
@@ -138,10 +139,11 @@ object CameraHelper{
camera.parameters = parameters
}
- fun getCameraInfo(camera:Camera): CameraInfo {
+ fun getCameraInfo(camera: Camera): CameraInfo {
val size = camera.parameters.previewSize
val picSize = camera.parameters.pictureSize
- return CameraInfo(size.width, size.height, Camera.CameraInfo().orientation, cameraId == Camera.CameraInfo.CAMERA_FACING_FRONT, picSize.width, picSize.height)
+ return CameraInfo(size.width, size.height, Camera.CameraInfo().orientation,
+ cameraId == Camera.CameraInfo.CAMERA_FACING_FRONT, picSize.width, picSize.height)
}
/**
@@ -168,14 +170,15 @@ object CameraHelper{
fun getLargePreviewSize(camera: Camera?): Camera.Size? {
if (camera != null) {
//获取可选比例
- Collections.sort(camera.parameters.supportedPictureSizes, Comparator { o1, o2 ->
- if (o1.width > o2.width) {
- return@Comparator -1
- } else if (o1.width < o2.width) {
- return@Comparator 1
- }
- 0
- })
+ Collections.sort(camera.parameters.supportedPictureSizes,
+ Comparator { o1, o2 ->
+ if (o1.width > o2.width) {
+ return@Comparator -1
+ } else if (o1.width < o2.width) {
+ return@Comparator 1
+ }
+ 0
+ })
for (size in camera.parameters.supportedPictureSizes) {
if (size.height <= 720) {
diff --git a/app/src/main/java/com/cangwang/magic/util/CorountinesUtil.kt b/app/src/main/java/com/cangwang/magic/util/CorountinesUtil.kt
new file mode 100644
index 0000000..4e0c74c
--- /dev/null
+++ b/app/src/main/java/com/cangwang/magic/util/CorountinesUtil.kt
@@ -0,0 +1,7 @@
+package com.cangwang.magic.util
+
+import kotlinx.coroutines.newFixedThreadPoolContext
+
+object CorountinesUtil {
+ val Background = newFixedThreadPoolContext(2, "bg")
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/cangwang/magic/util/Dipatcher.kt b/app/src/main/java/com/cangwang/magic/util/Dipatcher.kt
new file mode 100644
index 0000000..9646f09
--- /dev/null
+++ b/app/src/main/java/com/cangwang/magic/util/Dipatcher.kt
@@ -0,0 +1,59 @@
+package com.cangwang.magic.util
+
+import android.util.Log
+import io.reactivex.Observable
+import io.reactivex.disposables.Disposable
+import io.reactivex.schedulers.Schedulers
+import java.lang.Exception
+import java.util.concurrent.LinkedBlockingDeque
+import java.util.concurrent.ThreadPoolExecutor
+import java.util.concurrent.TimeUnit
+
+object Dipatcher{
+
+ fun singleDipatcher(executor: ThreadPoolExecutor):DipatchImpl{
+ return DipatchImpl(executor)
+ }
+
+ interface IDipatcher{
+ fun dipatch(runnable:()->Unit)
+ fun stop(runnable: () -> Unit)
+ }
+
+ class IODipatchImpl(minThreadCount:Int,maxThreadCount:Int):IDipatcher{
+
+ private val ioExecutors = Schedulers.from(ThreadPoolExecutor(minThreadCount,maxThreadCount,60L,TimeUnit.SECONDS,LinkedBlockingDeque()))
+
+ override fun dipatch(runnable: () -> Unit) {
+
+ }
+
+ override fun stop(runnable: () -> Unit) {
+
+ }
+ }
+
+ class DipatchImpl(executor: ThreadPoolExecutor):IDipatcher{
+ private var scheduler = Schedulers.from(executor)
+ private var mDispose:Disposable?=null
+
+ override fun dipatch(runnable: () -> Unit) {
+ mDispose= Observable.just(1)
+ .observeOn(scheduler)
+ .subscribe{
+ try {
+ runnable.invoke()
+ }catch (e:Exception){
+ Log.e("DipatchImpl",e.toString())
+ }
+ }
+
+ }
+
+ override fun stop(runnable: () -> Unit) {
+ if(mDispose?.isDisposed == false){
+ mDispose?.dispose()
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/cangwang/magic/util/ExifUtil.kt b/app/src/main/java/com/cangwang/magic/util/ExifUtil.kt
index f78cff9..c9eadb1 100644
--- a/app/src/main/java/com/cangwang/magic/util/ExifUtil.kt
+++ b/app/src/main/java/com/cangwang/magic/util/ExifUtil.kt
@@ -10,6 +10,10 @@ object ExifUtil{
fun getExifOrientation(filepath: String): Int {
var degree = 0
+ if (filepath.endsWith(".png")){
+ Log.d(TAG,"png file degree 0")
+ return degree
+ }
var exif: ExifInterface? = null
try {
exif = ExifInterface(filepath)
diff --git a/app/src/main/java/com/cangwang/magic/util/FilterHelper.kt b/app/src/main/java/com/cangwang/magic/util/FilterHelper.kt
new file mode 100755
index 0000000..c1cdae1
--- /dev/null
+++ b/app/src/main/java/com/cangwang/magic/util/FilterHelper.kt
@@ -0,0 +1,294 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+package com.cangwang.magic.util
+
+import android.app.AlertDialog
+import android.content.Context
+import android.widget.Toast
+import com.cangwang.gpuimage.GPUImageFilter
+
+import java.util.LinkedList
+
+object FilterHelper {
+ internal val FILTER_BRIGHTNESS = 0
+ internal val FILTER_COLOR_INVERT = 1
+ internal val FILTER_GRAYSCALE = 2
+ internal val FILTER_GAUSSIAN_BLUR = 3
+ internal val FILTER_BILATERAL = 4
+ internal val FILTER_IOS_BLUR = 5
+ internal val FILTER_CANNY_EDGE_DETECTION = 6
+ internal val FILTER_WEAK_PIXEL_INCLUSION = 7
+ internal val FILTER_NON_MAXIMUM_SUPPRESSION = 8
+ internal val FILTER_BEAUTIFY = 9
+ internal val FILTER_SOBEL_EDGE_DETECTION = 10
+ internal val FILTER_SKETCH = 11
+ internal val FILTER_TOON = 12
+ internal val FILTER_SMOOTH_TOON = 13
+ internal val FILTER_POSTERIZE = 14
+ internal val FILTER_PIXELLATION = 15
+ internal val FILTER_SATURATION = 16
+ internal val FILTER_CONTRAST = 17
+ internal val FILTER_EXPOSURE = 18
+ internal val FILTER_RGB = 19
+ internal val FILTER_HUE = 20
+ internal val FILTER_WHITE_BALANCE = 21
+ internal val FILTER_LUMINANCE_RANGE = 22
+ internal val FILTER_EMBOSS = 23
+ internal val FILTER_HALFTONE = 24
+ internal val FILTER_CROSSHATCH = 25
+ internal val FILTER_SPHERE_REFRACTION = 26
+ internal val FILTER_GLASS_SPHERE = 27
+
+ private var filterList: FilterList? = null
+
+ private fun getFilterList(): FilterList {
+ if (filterList == null) {
+ filterList = FilterList()
+ filterList!!.addFilter(FILTER_BRIGHTNESS, "Brightness", "BrightnessFilter")
+ filterList!!.addFilter(FILTER_COLOR_INVERT, "Color Invert", "ColorInvertFilter")
+ filterList!!.addFilter(FILTER_GRAYSCALE, "Grayscale", "GrayscaleFilter")
+ filterList!!.addFilter(FILTER_GAUSSIAN_BLUR, "Gaussian Blur", "GaussianBlurFilter")
+ filterList!!.addFilter(FILTER_BILATERAL, "Bilateral", "BilateralFilter")
+ filterList!!.addFilter(FILTER_IOS_BLUR, "iOS 7 Blur", "IOSBlurFilter")
+ filterList!!.addFilter(FILTER_CANNY_EDGE_DETECTION, "Canny Edge Detection",
+ "CannyEdgeDetectionFilter")
+ filterList!!.addFilter(FILTER_WEAK_PIXEL_INCLUSION, "Weak Pixel Inclusion",
+ "WeakPixelInclusionFilter")
+ filterList!!.addFilter(FILTER_NON_MAXIMUM_SUPPRESSION, "Non Maximum Suppression",
+ "NonMaximumSuppressionFilter")
+ filterList!!.addFilter(FILTER_BEAUTIFY, "Beautify", "BeautifyFilter")
+ filterList!!.addFilter(FILTER_SOBEL_EDGE_DETECTION, "Sobel Edge Detection",
+ "SobelEdgeDetectionFilter")
+ filterList!!.addFilter(FILTER_SKETCH, "Sketch", "SketchFilter")
+ filterList!!.addFilter(FILTER_TOON, "Toon", "ToonFilter")
+ filterList!!.addFilter(FILTER_SMOOTH_TOON, "Smooth Toon", "SmoothToonFilter")
+ filterList!!.addFilter(FILTER_POSTERIZE, "Posterize", "PosterizeFilter")
+ filterList!!.addFilter(FILTER_PIXELLATION, "Pixellation", "PixellationFilter")
+ filterList!!.addFilter(FILTER_SATURATION, "Saturation", "SaturationFilter")
+ filterList!!.addFilter(FILTER_CONTRAST, "Contrast", "ContrastFilter")
+ filterList!!.addFilter(FILTER_EXPOSURE, "Exposure", "ExposureFilter")
+ filterList!!.addFilter(FILTER_RGB, "RGB Adjustment", "RGBFilter")
+ filterList!!.addFilter(FILTER_HUE, "Hue Adjustment", "HueFilter")
+ filterList!!.addFilter(FILTER_WHITE_BALANCE, "White Balance", "WhiteBalanceFilter")
+ filterList!!.addFilter(FILTER_LUMINANCE_RANGE, "Luminance Range",
+ "LuminanceRangeFilter")
+ filterList!!.addFilter(FILTER_EMBOSS, "Emboss Filter", "EmbossFilter")
+ filterList!!.addFilter(FILTER_HALFTONE, "Halftone Filter", "HalftoneFilter")
+ filterList!!.addFilter(FILTER_CROSSHATCH, "Crosshatch Filter", "CrosshatchFilter")
+ filterList!!.addFilter(FILTER_SPHERE_REFRACTION, "Sphere Refraction Filter",
+ "SphereRefractionFilter")
+ filterList!!.addFilter(FILTER_GLASS_SPHERE, "Glass Sphere Filter", "GlassSphereFilter")
+ }
+ return filterList!!
+ }
+
+ fun showListDialog(
+ context: Context,
+ listener: OnFilterSelectedListener
+ ) {
+
+ val filters = getFilterList()
+ val builder = AlertDialog.Builder(context)
+ builder.setTitle("Choose a filter")
+ builder.setItems(filters.displayNames.toTypedArray()
+ ) { dialog, item ->
+ Toast.makeText(context, filters.displayNames[item],
+ Toast.LENGTH_SHORT).show()
+ listener.OnFilterSelected(createFilter(filters.filters[item]))
+ }
+ builder.create().show()
+ }
+
+ fun applyFilterWithSliderValue(filter: GPUImageFilter, v: Float) {
+ var value = v
+ val filters = getFilterList()
+ val filterClassName = filter.filterClassName
+ when (filters.classNames.indexOf(filterClassName)) {
+ FILTER_BRIGHTNESS -> {
+ run {
+ // let the value between -1 and 1
+ value = (value - 0.5f) * 2.0f
+ filter.setProperty("brightness", value)
+ }
+ }
+ FILTER_COLOR_INVERT -> {
+ run { }
+ }
+ FILTER_GRAYSCALE -> {
+ run { }
+ }
+ FILTER_GAUSSIAN_BLUR -> {
+ run {
+ // let the value between 0 - 24
+ value *= 24.0f
+ //filter->setProperty("radius", (int)value);
+ filter.setProperty("sigma", value)
+ }
+ }
+ FILTER_IOS_BLUR -> {
+ run {
+ value = value * 10.0f + 1.0f
+ filter.setProperty("downSampling", value)
+ }
+ }
+ FILTER_BILATERAL -> {
+ run {
+ // let the value between 0 - 10
+ value *= 10.0f
+ filter.setProperty("distanceNormalizationFactor", value)
+ }
+ }
+ FILTER_CANNY_EDGE_DETECTION -> {
+ run {
+ //todo
+ }
+ }
+ FILTER_WEAK_PIXEL_INCLUSION -> {
+ run { }
+ }
+ FILTER_NON_MAXIMUM_SUPPRESSION -> {
+ run {
+ value *= 5.0f
+ filter.setProperty("texelSizeMultiplier", value)
+ }
+ }
+ FILTER_BEAUTIFY -> {
+ run { }
+ }
+ FILTER_SOBEL_EDGE_DETECTION -> {
+ run { filter.setProperty("edgeStrength", value) }
+ }
+ FILTER_SKETCH -> {
+ run { filter.setProperty("edgeStrength", value) }
+ }
+ FILTER_TOON -> {
+ run {
+ value *= 20.0f
+ filter.setProperty("quantizationLevels", value)
+ }
+ }
+ FILTER_SMOOTH_TOON -> {
+ run {
+ // let the value between 1 - 6
+ value = value * 5.0f + 1.0f
+ filter.setProperty("blurRadius", value.toInt())
+ }
+ }
+ FILTER_POSTERIZE -> {
+ run {
+ // let the value between 1 and 256
+ value = value * 19.0f + 1.0f
+ filter.setProperty("colorLevels", value.toInt())
+ }
+ }
+ FILTER_PIXELLATION -> {
+ run { filter.setProperty("pixelSize", value) }
+ }
+ FILTER_SATURATION -> {
+ run {
+ // let the value between 0 - 2
+ value *= 2.0f
+ filter.setProperty("saturation", value)
+ }
+ }
+ FILTER_CONTRAST -> {
+ run {
+ value *= 4.0f
+ filter.setProperty("contrast", value)
+ }
+ }
+ FILTER_EXPOSURE -> {
+ run {
+ // let the value between -10 and 10
+ value = (value - 0.5f) * 20.0f
+ filter.setProperty("exposure", value)
+ }
+ }
+ FILTER_RGB -> {
+ run {
+ value *= 2.0f
+ filter.setProperty("greenAdjustment", value)
+ }
+ }
+ FILTER_HUE -> {
+ run {
+ value *= 360f
+ filter.setProperty("hueAdjustment", value)
+ }
+ }
+ FILTER_WHITE_BALANCE -> {
+ run {
+ value = value * 5000.0f + 2500.0f
+ filter.setProperty("temperature", value)
+ }
+ }
+ FILTER_LUMINANCE_RANGE -> {
+ run { filter.setProperty("rangeReductionFactor", value) }
+ }
+ FILTER_EMBOSS -> {
+ run {
+ value *= 4.0f
+ filter.setProperty("intensity", value)
+ }
+ }
+ FILTER_HALFTONE -> {
+ run {
+ value *= 0.05f
+ filter.setProperty("pixelSize", value)
+ }
+ }
+ FILTER_CROSSHATCH -> {
+ run {
+ value = 0.01f + value * 0.05f
+ filter.setProperty("crossHatchSpacing", value)
+ }
+ }
+ FILTER_SPHERE_REFRACTION -> {
+ run { filter.setProperty("radius", value) }
+ }
+ FILTER_GLASS_SPHERE -> {
+ run { filter.setProperty("radius", value) }
+ }
+ else -> {
+ }
+ }
+ }
+
+ private fun createFilter(type: Int): GPUImageFilter {
+ val filters = getFilterList()
+ val filterClassName = filters.classNames[type]
+ return GPUImageFilter.create(filterClassName)
+ }
+
+ private class FilterList {
+ var filters: MutableList = LinkedList()
+ var displayNames: MutableList = LinkedList()
+ var classNames: MutableList = LinkedList()
+
+ fun addFilter(filter: Int, displayName: String, className: String) {
+ filters.add(filter)
+ displayNames.add(displayName)
+ classNames.add(className)
+ }
+ }
+
+ interface OnFilterSelectedListener {
+ fun OnFilterSelected(newFilter: GPUImageFilter)
+ }
+}
diff --git a/app/src/main/java/com/cangwang/magic/util/OpenGLJniLib.kt b/app/src/main/java/com/cangwang/magic/util/OpenGLJniLib.kt
deleted file mode 100644
index 9a562a3..0000000
--- a/app/src/main/java/com/cangwang/magic/util/OpenGLJniLib.kt
+++ /dev/null
@@ -1,98 +0,0 @@
-package com.cangwang.magic.util
-
-import android.content.res.AssetManager
-import android.view.Surface
-
-/**
- * openGL辅助类
- * Created by cangwang on 2018/10/12.
- */
-object OpenGLJniLib{
- init {
- System.loadLibrary("magicjni")
- }
-
- /**
- * 初始化magicBaseView
- */
- external fun magicBaseInit(surface:Surface, width:Int, height:Int, manager: AssetManager):Int
-
- /**
- * 创建magicBaseView
- */
- external fun magicBaseCreate()
-
- /**
- * 变更触发magicBaseView
- */
- external fun magicBaseChange(width:Int,height:Int)
-
- /**
- * 绘制
- */
- external fun magicBaseDraw(matrix:FloatArray)
-
- external fun magicBaseRelease()
-
- /**
- * 调整大小
- */
- external fun magicAdjustSize(orientation:Int,isFront:Boolean,flipVertical:Boolean)
-
-
- /**
- * 相机滤镜创建
- */
- external fun magicFilterCreate(surface:Surface,manager: AssetManager):Int
-
- external fun magicFilterChange(width:Int,height:Int)
-
- external fun magicFilterDraw(matrix:FloatArray,isTakePhoto:String)
-
- external fun magicFilterRelease()
-
-
- /**
- * 图片滤镜创建
- */
- external fun magicImageFilterCreate(surface:Surface,manager: AssetManager,path:String,degree:Int):Int
-
- external fun magicImageFilterChange(width:Int,height:Int)
-
- external fun magicImageFilterDraw(matrix:FloatArray,isSavePhoto:String)
-
- external fun magicImageFilterRelease()
-
- /**
- * 设置美颜级别
- */
- external fun setImageBeautyLevel(level:Int)
-
-
- /**
- * 获取滤镜列表
- */
- external fun getFilterTypes():IntArray
-
- /**
- * 设置滤镜类型
- */
- external fun setFilterType(type:Int)
-
- external fun setImageFilterType(type:Int)
-
- /**
- * 设置美颜级别
- */
- external fun setBeautyLevel(level:Int)
-
- /**
- * 摄像头保存图片
- */
- external fun savePhoto(address:String):Boolean
-
- /**
- * 编辑保存图片
- */
- external fun saveImage(address: String):Boolean
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/cangwang/magic/util/RenderJNI.kt b/app/src/main/java/com/cangwang/magic/util/RenderJNI.kt
index 5c22652..ee5c116 100644
--- a/app/src/main/java/com/cangwang/magic/util/RenderJNI.kt
+++ b/app/src/main/java/com/cangwang/magic/util/RenderJNI.kt
@@ -9,7 +9,7 @@ import javax.microedition.khronos.opengles.GL10
/**
* Created by cangwang on 2018/10/12.
*/
-class RenderJNI(context: Context):GLSurfaceView.Renderer{
+class RenderJNI(context: Context) : GLSurfaceView.Renderer {
companion object {
init {
System.loadLibrary("triangle-lib")
@@ -18,23 +18,21 @@ class RenderJNI(context: Context):GLSurfaceView.Renderer{
external fun glesInit()
external fun glesRender()
- external fun glesResize(width:Int,height:Int)
+ external fun glesResize(width: Int, height: Int)
external fun readShaderFile(assetManager: AssetManager)
- val assetMaanager:AssetManager = context.assets
-
+ val assetMaanager: AssetManager = context.assets
override fun onDrawFrame(p0: GL10?) {
glesRender()
}
override fun onSurfaceChanged(p0: GL10?, width: Int, height: Int) {
- glesResize(width,height)
+ glesResize(width, height)
}
override fun onSurfaceCreated(p0: GL10?, p1: EGLConfig?) {
readShaderFile(assetMaanager)
glesInit()
}
-
}
\ No newline at end of file
diff --git a/app/src/main/java/com/cangwang/magic/video/AudioEncoderCoder.kt b/app/src/main/java/com/cangwang/magic/video/AudioEncoderCoder.kt
new file mode 100644
index 0000000..00f3324
--- /dev/null
+++ b/app/src/main/java/com/cangwang/magic/video/AudioEncoderCoder.kt
@@ -0,0 +1,166 @@
+package com.cangwang.magic.video
+
+import android.media.MediaCodec
+import android.media.MediaCodecInfo
+import android.media.MediaFormat
+import android.util.Log
+import java.io.FileNotFoundException
+import java.io.IOException
+import java.nio.ByteBuffer
+
+/**
+ * Created by cangwang on 2019.3.6
+ * 录制完整mp4短视频音轨
+ */
+class AudioEncoderCoder(muxer:MediaMuxerCoder?){
+ private val TAG = AudioEncoderCoder::class.java.simpleName
+ private var audioEncoder:MediaCodec?=null
+ private val SAMPLE_RATE = 44100
+ private val mBufferInfo = MediaCodec.BufferInfo()
+ private var mMuxer:MediaMuxerCoder?=null
+
+ init {
+ audioEncoder = MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_AUDIO_AAC)
+ val format = MediaFormat.createAudioFormat(MediaFormat.MIMETYPE_AUDIO_AAC,SAMPLE_RATE,2)
+ format.setInteger(MediaFormat.KEY_BIT_RATE, 96000)
+ format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, DEFAULT_BUFFER_SIZE)
+ format.setInteger(MediaFormat.KEY_AAC_PROFILE,MediaCodecInfo.CodecProfileLevel.AACObjectLC)
+ audioEncoder?.configure(format,null,null,MediaCodec.CONFIGURE_FLAG_ENCODE)
+ mMuxer=muxer
+ }
+
+ fun start(){
+ audioEncoder?.start()
+ }
+
+ fun release(){
+ audioEncoder?.stop()
+ audioEncoder?.release()
+ audioEncoder = null
+ }
+
+ var prevPresentationTimes = mBufferInfo.presentationTimeUs
+ private fun getPTSUs(): Long {
+ var result = System.nanoTime() / 1000
+ if (result < prevPresentationTimes) {
+ result += prevPresentationTimes - result
+ }
+ return result
+ }
+
+ var encoderOutputBuffers:Array?=null
+ fun encodePCMToAAC(bytes:ByteArray){
+ try {
+ audioEncoder?.apply {
+ val inputBufferIndex = dequeueInputBuffer(0)
+ if (inputBufferIndex > 0){
+ val inputBuffer = getInputBuffer(inputBufferIndex)
+ inputBuffer.clear()
+ inputBuffer.put(bytes)
+ audioEncoder?.queueInputBuffer(inputBufferIndex,0,bytes.size,getPTSUs(),0)
+ }
+
+ while (true) {
+ val encoderStatus = dequeueOutputBuffer(mBufferInfo, 0)
+
+ if (encoderStatus == MediaCodec.INFO_TRY_AGAIN_LATER) {
+ Log.d(TAG, "no output available, spinning to await EOS")
+ break
+ } else if (encoderStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
+ // not expected for an encoder
+ encoderOutputBuffers = outputBuffers
+ } else if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+ //一定要在这个节点上获取fomart设置到混合器的音轨上
+ // should happen before receiving buffers, and should only happen once
+ if (mMuxer?.hasAudioTrack() == true) {
+ Log.d(TAG,"audio format changed twice")
+ break
+ }
+ val newFormat = outputFormat
+ Log.d(TAG, "encoder output format changed: $newFormat")
+
+ // now that we have the Magic Goodies, start the muxer
+ val track = mMuxer?.setAudioTrack(newFormat)
+ Log.d(TAG, "audiotrack: $track")
+ mMuxer?.start()
+ } else if (encoderStatus < 0) {
+ Log.w(TAG, "unexpected result from encoder.dequeueOutputBuffer: $encoderStatus")
+ // let's ignore it
+ } else {
+ encoderOutputBuffers = outputBuffers
+ if (encoderOutputBuffers != null) {
+ val encodedData = encoderOutputBuffers!![encoderStatus]
+
+ if (mBufferInfo.flags and MediaCodec.BUFFER_FLAG_CODEC_CONFIG != 0) {
+ // The codec config data was pulled out and fed to the muxer when we got
+ // the INFO_OUTPUT_FORMAT_CHANGED status. Ignore it.
+ Log.d(TAG, "ignoring BUFFER_FLAG_CODEC_CONFIG")
+ mBufferInfo.size = 0
+ }
+
+ if (mBufferInfo.size != 0) {
+ if (mMuxer?.isRecording() == false) {
+ Log.d(TAG,"muxer hasn't started")
+ //释放采集的音轨数据
+ releaseOutputBuffer(encoderStatus, false)
+ break
+// throw RuntimeException("muxer hasn't started")
+ }
+
+ val outputBufferSize = encodedData.limit() + 7 // ADTS头部是7个字节
+ val aacBytes = ByteArray(outputBufferSize)
+ addADTStoPacket(aacBytes,outputBufferSize)
+ encodedData.get(aacBytes,7,encodedData.limit())
+ mBufferInfo.presentationTimeUs = getPTSUs()
+ mMuxer?.writeAudioData(encodedData,mBufferInfo)
+
+// Log.d(TAG, "sent " + mBufferInfo.size + " bytes to muxer, ts=" + mBufferInfo.presentationTimeUs)
+ }
+ //释放采集的音轨数据
+ releaseOutputBuffer(encoderStatus, false)
+
+ if (mBufferInfo.flags and MediaCodec.BUFFER_FLAG_END_OF_STREAM != 0) {
+ Log.d(TAG, "end of stream reached")
+ break // out of while
+ }
+ }
+ }
+ }
+ }
+ }catch (e:FileNotFoundException){
+ Log.e(TAG,e.toString())
+ }catch (e:IOException){
+ Log.e(TAG,e.toString())
+ }
+ }
+
+ private fun addADTStoPacket(packet: ByteArray, packetLen: Int) {
+ val profile = 2 //AAC LC,MediaCodecInfo.CodecProfileLevel.AACObjectLC;
+ val freqIdx = 4 //见后面注释avpriv_mpeg4audio_sample_rates中32000对应的数组下标,来自ffmpeg源码
+ val chanCfg = 1 //见后面注释channel_configuration,AudioFormat.CHANNEL_IN_MONO 单声道(声道数量)
+
+ /*int avpriv_mpeg4audio_sample_rates[] = {96000, 88200, 64000, 48000, 44100, 32000,24000, 22050, 16000, 12000, 11025, 8000, 7350};
+ channel_configuration: 表示声道数chanCfg
+ 0: Defined in AOT Specifc Config
+ 1: 1 channel: front-center
+ 2: 2 channels: front-left, front-right
+ 3: 3 channels: front-center, front-left, front-right
+ 4: 4 channels: front-center, front-left, front-right, back-center
+ 5: 5 channels: front-center, front-left, front-right, back-left, back-right
+ 6: 6 channels: front-center, front-left, front-right, back-left, back-right, LFE-channel
+ 7: 8 channels: front-center, front-left, front-right, side-left, side-right, back-left, back-right, LFE-channel
+ 8-15: Reserved
+ */
+
+ // fill in ADTS data
+ packet[0] = 0xFF.toByte()
+ //packet[1] = (byte)0xF9;
+ packet[1] = 0xF1.toByte()//解决ios 不能播放问题
+ packet[2] = ((profile - 1).shl(6) + (freqIdx shl 2)+(chanCfg shr 2)).toByte()
+ packet[3] = ((chanCfg and 3 shl 6) + (packetLen shr 11)).toByte()
+ packet[4] = (packetLen and 0x7FF shr 3).toByte()
+ packet[5] = ((packetLen and 7 shl 5) + 0x1F).toByte()
+ packet[6] = 0xFC.toByte()
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/cangwang/magic/video/AudioEncoderCoderAAC.kt b/app/src/main/java/com/cangwang/magic/video/AudioEncoderCoderAAC.kt
new file mode 100644
index 0000000..d1314d0
--- /dev/null
+++ b/app/src/main/java/com/cangwang/magic/video/AudioEncoderCoderAAC.kt
@@ -0,0 +1,113 @@
+package com.cangwang.magic.video
+
+import android.media.MediaCodec
+import android.media.MediaCodecInfo
+import android.media.MediaFormat
+import android.util.Log
+import java.io.FileNotFoundException
+import java.io.FileOutputStream
+import java.io.IOException
+
+/**
+ * Created by cangwang on 2019.3.6
+ * 单独AAC音频录制
+ */
+class AudioEncoderCoderAAC(address:String){
+ private val TAG = AudioEncoderCoder::class.java.simpleName
+ private var audioEncoder:MediaCodec?=null
+ private val SAMPLE_RATE = 44100
+ private val mBufferInfo = MediaCodec.BufferInfo()
+ private var address: String
+ private var mFileStream:FileOutputStream?=null
+
+ init {
+ audioEncoder = MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_AUDIO_AAC)
+ val format = MediaFormat.createAudioFormat(MediaFormat.MIMETYPE_AUDIO_AAC,SAMPLE_RATE,2)
+ format.setInteger(MediaFormat.KEY_BIT_RATE, 96000)
+ format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, DEFAULT_BUFFER_SIZE)
+ format.setInteger(MediaFormat.KEY_AAC_PROFILE,MediaCodecInfo.CodecProfileLevel.AACObjectLC)
+ audioEncoder?.configure(format,null,null,MediaCodec.CONFIGURE_FLAG_ENCODE)
+ this.address = address
+ mFileStream = FileOutputStream(address)
+ }
+
+ fun start(){
+ audioEncoder?.start()
+ }
+
+ fun release(){
+ if (mFileStream !=null){
+ try {
+ mFileStream?.flush()
+ mFileStream?.close()
+ }catch (e:IOException){
+ Log.e(TAG,e.toString())
+ }
+ }
+ audioEncoder?.stop()
+ audioEncoder?.release()
+ audioEncoder =null
+ }
+
+
+ fun encodePCMToAAC(bytes:ByteArray){
+ try {
+ audioEncoder?.apply {
+ val inputBufferIndex = dequeueInputBuffer(0)
+ if (inputBufferIndex > 0){
+ val inputBuffer = getInputBuffer(inputBufferIndex)
+ inputBuffer.clear()
+ inputBuffer.put(bytes)
+ audioEncoder?.queueInputBuffer(inputBufferIndex,0,bytes.size,System.nanoTime(),0)
+ }
+
+ var outputBufferIndex = dequeueOutputBuffer(mBufferInfo,0)
+ while (outputBufferIndex>0){
+ val outputBuffer = getOutputBuffer(outputBufferIndex)
+ val outputBufferSize = outputBuffer.limit() + 7 // ADTS头部是7个字节
+ val aacBytes = ByteArray(outputBufferSize)
+ addADTStoPacket(aacBytes,outputBufferSize)
+ outputBuffer.get(aacBytes,7,outputBuffer.limit())
+ mFileStream?.write(aacBytes)
+
+ releaseOutputBuffer(outputBufferIndex,false)
+ outputBufferIndex = dequeueOutputBuffer(mBufferInfo,0)
+ }
+ }
+ }catch (e:FileNotFoundException){
+ Log.e(TAG,e.toString())
+ }catch (e:IOException){
+ Log.e(TAG,e.toString())
+ }
+ }
+
+ private fun addADTStoPacket(packet: ByteArray, packetLen: Int) {
+ val profile = 2 //AAC LC,MediaCodecInfo.CodecProfileLevel.AACObjectLC;
+ val freqIdx = 4 //见后面注释avpriv_mpeg4audio_sample_rates中32000对应的数组下标,来自ffmpeg源码
+ val chanCfg = 1 //见后面注释channel_configuration,AudioFormat.CHANNEL_IN_MONO 单声道(声道数量)
+
+ /*int avpriv_mpeg4audio_sample_rates[] = {96000, 88200, 64000, 48000, 44100, 32000,24000, 22050, 16000, 12000, 11025, 8000, 7350};
+ channel_configuration: 表示声道数chanCfg
+ 0: Defined in AOT Specifc Config
+ 1: 1 channel: front-center
+ 2: 2 channels: front-left, front-right
+ 3: 3 channels: front-center, front-left, front-right
+ 4: 4 channels: front-center, front-left, front-right, back-center
+ 5: 5 channels: front-center, front-left, front-right, back-left, back-right
+ 6: 6 channels: front-center, front-left, front-right, back-left, back-right, LFE-channel
+ 7: 8 channels: front-center, front-left, front-right, side-left, side-right, back-left, back-right, LFE-channel
+ 8-15: Reserved
+ */
+
+ // fill in ADTS data
+ packet[0] = 0xFF.toByte()
+ //packet[1] = (byte)0xF9;
+ packet[1] = 0xF1.toByte()//解决ios 不能播放问题
+ packet[2] = ((profile - 1).shl(6) + (freqIdx shl 2)+(chanCfg shr 2)).toByte()
+ packet[3] = ((chanCfg and 3 shl 6) + (packetLen shr 11)).toByte()
+ packet[4] = (packetLen and 0x7FF shr 3).toByte()
+ packet[5] = ((packetLen and 7 shl 5) + 0x1F).toByte()
+ packet[6] = 0xFC.toByte()
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/cangwang/magic/video/AudioRecordCoder.kt b/app/src/main/java/com/cangwang/magic/video/AudioRecordCoder.kt
new file mode 100644
index 0000000..c69df5b
--- /dev/null
+++ b/app/src/main/java/com/cangwang/magic/video/AudioRecordCoder.kt
@@ -0,0 +1,101 @@
+package com.cangwang.magic.video
+
+import android.media.AudioFormat
+import android.media.AudioRecord
+import android.media.MediaRecorder
+import android.util.Log
+import java.util.concurrent.atomic.AtomicBoolean
+
+/**
+ * Created by cangwang on 2019.3.6
+ * 录制完整mp4短视频音轨
+ */
+class AudioRecordCoder{
+ val TAG = AudioRecordCoder::class.java.simpleName
+ var SAMPLE_RATE = 44100
+ val CHANNEL = AudioFormat.CHANNEL_CONFIGURATION_STEREO
+ val AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT
+
+ var audioRecorder:AudioRecord?=null
+ var recordThread:Thread?=null
+ var bufferSizeInBytes = 0
+ var isRecoding = AtomicBoolean(false)
+ var audioEncoder:AudioEncoderCoder?=null
+
+ private var muxerCoder:MediaMuxerCoder?=null
+
+ init {
+ bufferSizeInBytes = AudioRecord.getMinBufferSize(SAMPLE_RATE,CHANNEL,AUDIO_FORMAT)
+ if (AudioRecord.ERROR_BAD_VALUE == bufferSizeInBytes || AudioRecord.ERROR == bufferSizeInBytes) {
+ Log.e(TAG,"bufferSizeInBytes not init")
+ }
+ audioRecorder = AudioRecord(MediaRecorder.AudioSource.MIC,SAMPLE_RATE,CHANNEL,AUDIO_FORMAT,bufferSizeInBytes)
+
+ if (audioRecorder == null || audioRecorder!!.state !=AudioRecord.STATE_INITIALIZED){
+ SAMPLE_RATE = 16000
+ bufferSizeInBytes = AudioRecord.getMinBufferSize(SAMPLE_RATE,CHANNEL,AUDIO_FORMAT)
+ audioRecorder = AudioRecord(MediaRecorder.AudioSource.MIC,SAMPLE_RATE,CHANNEL,AUDIO_FORMAT,bufferSizeInBytes)
+ }
+ if (audioRecorder!!.state !=AudioRecord.STATE_INITIALIZED){
+ Log.e(TAG,"audio record not init")
+ }
+
+ }
+
+ fun start(muxer: MediaMuxerCoder?){
+ if(audioRecorder?.state == AudioRecord.STATE_INITIALIZED) {
+ muxerCoder = muxer
+ audioRecorder?.run {
+ if (state != AudioRecord.STATE_INITIALIZED) {
+ null
+ } else {
+ startRecording()
+ }
+ }
+ isRecoding.set(true)
+ audioEncoder = AudioEncoderCoder(muxerCoder)
+ recordThread = Thread(RecordThread(), "AudioRecordThread")
+ recordThread?.start()
+ audioEncoder?.start()
+ }
+ }
+
+ fun stop(){
+ if(audioRecorder?.state == AudioRecord.STATE_INITIALIZED) {
+ audioRecorder?.run {
+ Log.d(TAG,"stop audio")
+ isRecoding.set(false)
+ recordThread?.join()
+ Log.d(TAG,"release")
+ audioEncoder?.release()
+ releaseAudioRecord()
+ }
+ }
+ }
+
+ private fun releaseAudioRecord(){
+ audioRecorder?.run {
+ stop()
+ release()
+ Log.d(TAG,"audio stop record")
+ }
+ }
+
+ fun getAudioRecordBuffer(bufferSizeInBytes:Int,audioSamples:ByteArray):Int{
+ audioRecorder?.run {
+ return read(audioSamples,0,bufferSizeInBytes)
+ }?:return 0
+ }
+
+ inner class RecordThread:Runnable{
+ override fun run() {
+ val audioSamples = ByteArray(bufferSizeInBytes)
+ while (isRecoding.get()){ //循环采集音轨
+ val audioSampleSize = getAudioRecordBuffer(bufferSizeInBytes,audioSamples)
+ if (audioSampleSize != 0){
+ audioEncoder?.encodePCMToAAC(audioSamples)
+ }
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/com/cangwang/magic/video/AudioRecordCoderAAC.kt b/app/src/main/java/com/cangwang/magic/video/AudioRecordCoderAAC.kt
new file mode 100644
index 0000000..edaa6d7
--- /dev/null
+++ b/app/src/main/java/com/cangwang/magic/video/AudioRecordCoderAAC.kt
@@ -0,0 +1,111 @@
+package com.cangwang.magic.video
+
+import android.media.AudioFormat
+import android.media.AudioRecord
+import android.media.MediaRecorder
+import android.util.Log
+
+/**
+ * Created by cangwang on 2019.3.6
+ * 单独AAC音频录制
+ */
+class AudioRecordCoderAAC{
+ val TAG = AudioRecordCoder::class.java.simpleName
+ var SAMPLE_RATE = 44100
+ val CHANNEL = AudioFormat.CHANNEL_CONFIGURATION_STEREO
+ val AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT
+
+ var audioRecorder:AudioRecord?=null
+ var recordThread:Thread?=null
+ var bufferSizeInBytes = 0
+ var isRecoding = false
+ var audioEncoder:AudioEncoderCoderAAC?=null
+
+ private var outputFilePath:String?=null
+
+ init {
+ bufferSizeInBytes = AudioRecord.getMinBufferSize(SAMPLE_RATE,CHANNEL,AUDIO_FORMAT)
+ if (AudioRecord.ERROR_BAD_VALUE == bufferSizeInBytes || AudioRecord.ERROR == bufferSizeInBytes) {
+ Log.e(TAG,"bufferSizeInBytes not init")
+ }
+ audioRecorder = AudioRecord(MediaRecorder.AudioSource.MIC,SAMPLE_RATE,CHANNEL,AUDIO_FORMAT,bufferSizeInBytes)
+
+ if (audioRecorder == null || audioRecorder!!.state !=AudioRecord.STATE_INITIALIZED){
+ SAMPLE_RATE = 16000
+ bufferSizeInBytes = AudioRecord.getMinBufferSize(SAMPLE_RATE,CHANNEL,AUDIO_FORMAT)
+ audioRecorder = AudioRecord(MediaRecorder.AudioSource.MIC,SAMPLE_RATE,CHANNEL,AUDIO_FORMAT,bufferSizeInBytes)
+ }
+ if (audioRecorder!!.state !=AudioRecord.STATE_INITIALIZED){
+ Log.e(TAG,"audio record not init")
+ }
+ }
+
+ fun initMeta(){
+ audioRecorder?.release()
+
+ bufferSizeInBytes = AudioRecord.getMinBufferSize(SAMPLE_RATE,CHANNEL,AUDIO_FORMAT)
+ audioRecorder = AudioRecord(MediaRecorder.AudioSource.MIC,SAMPLE_RATE,CHANNEL,AUDIO_FORMAT,bufferSizeInBytes)
+
+ if (audioRecorder == null || audioRecorder!!.state !=AudioRecord.STATE_INITIALIZED){
+ SAMPLE_RATE = 16000
+ bufferSizeInBytes = AudioRecord.getMinBufferSize(SAMPLE_RATE,CHANNEL,AUDIO_FORMAT)
+ audioRecorder = AudioRecord(MediaRecorder.AudioSource.MIC,SAMPLE_RATE,CHANNEL,AUDIO_FORMAT,bufferSizeInBytes)
+ }
+ }
+
+ fun start(filePath:String){
+ if(audioRecorder?.state == AudioRecord.STATE_INITIALIZED) {
+ audioRecorder?.run {
+ if (state != AudioRecord.STATE_INITIALIZED) {
+ null
+ } else {
+ startRecording()
+ }
+ }
+ audioEncoder = AudioEncoderCoderAAC(filePath)
+ isRecoding = true
+ outputFilePath = filePath
+ recordThread = Thread(RecordThread(), "AudioRecordThread")
+ recordThread?.start()
+ audioEncoder?.start()
+ Log.d(TAG,"audio $filePath ,start record")
+ }
+ }
+
+ fun stop(){
+ if(audioRecorder?.state == AudioRecord.STATE_INITIALIZED) {
+ audioRecorder?.run {
+ isRecoding = false
+ audioEncoder?.release()
+ recordThread?.join()
+ releaseAudioRecord()
+ }
+ }
+ }
+
+ private fun releaseAudioRecord(){
+ audioRecorder?.run {
+ stop()
+ release()
+ Log.d(TAG,"audio stop record")
+ }
+ }
+
+ fun getAudioRecordBuffer(bufferSizeInBytes:Int,audioSamples:ByteArray):Int{
+ audioRecorder?.run {
+ return read(audioSamples,0,bufferSizeInBytes)
+ }?:return 0
+ }
+
+ inner class RecordThread:Runnable{
+ override fun run() {
+ val audioSamples = ByteArray(bufferSizeInBytes)
+ while (isRecoding){
+ val audioSampleSize = getAudioRecordBuffer(bufferSizeInBytes,audioSamples)
+ if (audioSampleSize != 0){
+ audioEncoder?.encodePCMToAAC(audioSamples)
+ }
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/com/cangwang/magic/video/MediaMuxerCoder.kt b/app/src/main/java/com/cangwang/magic/video/MediaMuxerCoder.kt
new file mode 100644
index 0000000..9fe9290
--- /dev/null
+++ b/app/src/main/java/com/cangwang/magic/video/MediaMuxerCoder.kt
@@ -0,0 +1,117 @@
+package com.cangwang.magic.video
+
+import android.media.MediaCodec
+import android.media.MediaFormat
+import android.media.MediaMuxer
+import android.util.Log
+import java.io.File
+import java.nio.ByteBuffer
+import java.util.concurrent.atomic.AtomicBoolean
+
+/**
+ * Created by cangwang on 2019.3.6
+ * 录制完整mp4小视频混合器
+ */
+class MediaMuxerCoder(outFile: File){
+ private val TAG= MediaMuxerCoder::class.java.simpleName
+ private var mMuxer: MediaMuxer?=null
+ private var NONE_TRACK = -1
+ private var videoTrack = NONE_TRACK
+ private var audioTrack = NONE_TRACK
+ private var mMuxerStarted= AtomicBoolean(false)
+
+ init {
+ mMuxer = MediaMuxer(outFile.toString(),MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4)
+ }
+
+ /**
+ * 设置视轨
+ */
+ fun setVideoTrack(mediaFormat: MediaFormat):Int{
+ videoTrack = mMuxer?.addTrack(mediaFormat)?:-1
+ return videoTrack
+ }
+
+ /**
+ * 设置音轨
+ */
+ fun setAudioTrack(mediaFormat: MediaFormat):Int{
+ audioTrack = mMuxer?.addTrack(mediaFormat)?:-1
+ return audioTrack
+ }
+
+ fun reset(outFile: File){
+ release()
+ mMuxer = MediaMuxer(outFile.toString(),MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4)
+ videoTrack = NONE_TRACK
+ audioTrack = NONE_TRACK
+ mMuxerStarted.set(false)
+ }
+
+ /**
+ * 开启混合器
+ */
+ fun start(){
+ //等待音轨和视轨同时设置完成后开启混合器
+ if (videoTrack != NONE_TRACK && audioTrack != NONE_TRACK) {
+ mMuxer?.start()
+ mMuxerStarted.set(true)
+ Log.d(TAG,"muxer start")
+ }
+ }
+
+ /**
+ * 是否已经写入音轨
+ */
+ fun hasAudioTrack():Boolean{
+ return audioTrack != NONE_TRACK
+ }
+
+ /**
+ * 是否已经写入视轨
+ */
+ fun hasVideoTrack():Boolean{
+ return videoTrack != NONE_TRACK
+ }
+
+ fun isRecording():Boolean{
+ return mMuxerStarted.get()
+ }
+
+ /**
+ * 写入视频数据
+ */
+ fun writeVideoData(byteBuffer: ByteBuffer,bufferInfo: MediaCodec.BufferInfo){
+ if (videoTrack != NONE_TRACK && mMuxerStarted.get()) {
+ writeData(videoTrack, byteBuffer, bufferInfo)
+ }
+ }
+
+ /**
+ * 写入音频数据
+ */
+ fun writeAudioData(byteBuffer: ByteBuffer,bufferInfo: MediaCodec.BufferInfo){
+ if (audioTrack != NONE_TRACK && mMuxerStarted.get()) {
+ writeData(audioTrack, byteBuffer, bufferInfo)
+ }
+ }
+
+ /**
+ * 写入数据到混合器
+ */
+ private fun writeData(track:Int, byteBuffer: ByteBuffer, bufferInfo: MediaCodec.BufferInfo){
+ synchronized(MediaMuxerCoder::class.java){
+ Log.d(TAG, "track = $track, sent " + bufferInfo.size + " bytes to muxer, ts=" + bufferInfo.presentationTimeUs)
+ mMuxer?.writeSampleData(track, byteBuffer, bufferInfo)
+ }
+ }
+
+ /**
+ * 释放混合器资源
+ */
+ fun release(){
+ mMuxer?.stop()
+ mMuxer?.release()
+ mMuxer=null
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/cangwang/magic/video/TextureMovieEncoder.kt b/app/src/main/java/com/cangwang/magic/video/TextureMovieEncoder.kt
new file mode 100644
index 0000000..bc8a145
--- /dev/null
+++ b/app/src/main/java/com/cangwang/magic/video/TextureMovieEncoder.kt
@@ -0,0 +1,157 @@
+package com.cangwang.magic.video
+
+import android.annotation.SuppressLint
+import android.os.Build
+import android.os.Environment
+import android.util.Log
+import com.cangwang.magic.BaseApplication
+import com.cangwang.filter.util.OpenGLJniLib
+import io.reactivex.Observable
+import io.reactivex.ObservableOnSubscribe
+import io.reactivex.functions.BiFunction
+import io.reactivex.schedulers.Schedulers
+import java.io.File
+import java.lang.Exception
+import java.util.concurrent.Executors
+import java.util.concurrent.atomic.AtomicBoolean
+
+/**
+ * Created by cangwang on 2019.3.6
+ * 录制完整mp4短视频
+ */
+class TextureMovieEncoder{
+ private val TAG = "TextureMovieEncoder"
+ private var videoEncoder:VideoEncoderCoder?=null
+ private var videoThread = Executors.newSingleThreadExecutor()
+ private var audioThread = Executors.newSingleThreadExecutor()
+ public var isReady = AtomicBoolean(false)
+ private var audioEncoder:AudioRecordCoder?=null
+ private var muxerEncoder:MediaMuxerCoder?=null
+
+ /**
+ * 开始采集
+ */
+ @SuppressLint("CheckResult")
+ fun startRecord(width:Int, height:Int, textureId:Int, filterType:Int){
+ //混合器
+ muxerEncoder = MediaMuxerCoder(File(getVideoFileAddress(System.currentTimeMillis())))
+ //开启视频和音频采集
+ Observable.zip(startVideo(width, height, textureId, filterType),startAudio(),
+ object: BiFunction{
+ override fun apply(isVideoReady: Boolean, isAudioReady: Boolean): Boolean {
+ return isVideoReady && isAudioReady
+ }
+ }).observeOn(Schedulers.io())
+ .subscribe ({
+ isReady.set(true)
+ },{
+ Log.e(TAG,"init error $it")
+ })
+ }
+
+ /**
+ * 视频采集
+ */
+ private fun startVideo(width:Int, height:Int, textureId:Int, filterType:Int):Observable{
+ return Observable.create(ObservableOnSubscribe {
+ if (width > 0 && height > 0) {
+ //码率为4*高*宽,使用滤镜,太低码率无法记录足够的细节
+ videoEncoder = VideoEncoderCoder(width, height, width*height*4, muxerEncoder)
+ videoEncoder?.apply {
+ OpenGLJniLib.buildVideoSurface(getInputSurface(), textureId, BaseApplication.context.assets)
+ OpenGLJniLib.magicVideoFilterChange(width,height)
+ if (filterType >= 0) {
+ OpenGLJniLib.setVideoFilterType(filterType)
+ }
+ start()
+ }
+ }
+ it.onNext(true)
+ }).subscribeOn(Schedulers.from(videoThread))
+ }
+
+ /**
+ * 音频采集
+ */
+ private fun startAudio():Observable{
+ return Observable.create(ObservableOnSubscribe {
+ audioEncoder = AudioRecordCoder()
+ audioEncoder?.start(muxerEncoder)
+ it.onNext(true)
+ }).subscribeOn(Schedulers.from(audioThread))
+ }
+
+ /**
+ * 停止录制
+ */
+ @SuppressLint("CheckResult")
+ fun stopRecord(){
+ Observable.zip(stopVideo(),stopAudio(),
+ object: BiFunction{
+ override fun apply(isVideoStop: Boolean, isAudioStop: Boolean): Boolean {
+ return isVideoStop && isAudioStop
+ }
+ }).observeOn(Schedulers.io())
+ .subscribe ({
+ muxerEncoder?.release()
+ Log.d(TAG,"muxer release")
+ },{
+ Log.e(TAG,it.toString())
+ })
+ }
+
+ /**
+ * 停止视频录制
+ */
+ private fun stopVideo():Observable{
+ return Observable.create(ObservableOnSubscribe {
+ isReady.set(false)
+ videoEncoder?.drainEncoder(true)
+ videoEncoder?.release()
+ videoEncoder = null
+ OpenGLJniLib.releaseVideoSurface()
+ it.onNext(true)
+ }).subscribeOn(Schedulers.from(videoThread))
+ }
+
+ /**
+ * 停止音频录制
+ */
+ private fun stopAudio():Observable{
+ return Observable.create(ObservableOnSubscribe {
+ audioEncoder?.stop()
+ it.onNext(true)
+ }).subscribeOn(Schedulers.from(audioThread))
+ }
+
+ /**
+ * 视频Surface绘制
+ */
+ fun drawFrame(matrix:FloatArray,time:Long){
+ if(isReady.get()) {
+ videoThread.execute {
+ videoEncoder?.apply {
+ try {
+ //传输视频帧数据
+ drainEncoder(false)
+ }catch (e:Exception){
+ Log.e(TAG,e.toString())
+ }
+ //绘制Suface
+ OpenGLJniLib.magicVideoDraw(matrix, time)
+ }
+ }
+ }
+ }
+
+ /**
+ * 获取文件地址
+ */
+ private fun getVideoFileAddress(time:Long): String {
+ return if(Build.BRAND == "Xiaomi"){ // 小米手机
+ Environment.getExternalStorageDirectory().path +"/DCIM/Camera/"+time+".mp4"
+ }else{ // Meizu 、Oppo
+ Environment.getExternalStorageDirectory().path +"/DCIM/"+time+".mp4"
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/cangwang/magic/video/TextureMovieEncoderSource.kt b/app/src/main/java/com/cangwang/magic/video/TextureMovieEncoderSource.kt
new file mode 100644
index 0000000..63a8aeb
--- /dev/null
+++ b/app/src/main/java/com/cangwang/magic/video/TextureMovieEncoderSource.kt
@@ -0,0 +1,90 @@
+package com.cangwang.magic.video
+
+import android.os.Build
+import android.os.Environment
+import android.util.Log
+import com.cangwang.magic.BaseApplication
+import com.cangwang.filter.util.OpenGLJniLib
+import java.io.File
+import java.lang.Exception
+import java.util.concurrent.Executors
+import java.util.concurrent.atomic.AtomicBoolean
+
+/**
+ * Created by cangwang on 2019.3.6
+ * 分别录制aac音频和mp4视频
+ */
+class TextureMovieEncoderSource{
+ private val TAG = "TextureMovieEncoder"
+ private var videoEncoder:VideoEncoderCoderMP4?=null
+ private var recordThread = Executors.newSingleThreadExecutor()
+ private var isReady = AtomicBoolean()
+ private var audioEncoder:AudioRecordCoderAAC?=null
+
+ init {
+ isReady.set(false)
+ }
+
+ fun startRecord(width:Int,height:Int,textureId:Int,filterType:Int){
+ val time = System.currentTimeMillis()
+ recordThread.execute {
+ if (width > 0 && height > 0) {
+ //码率为4*高*宽,使用滤镜,太低码率无法记录足够的细节
+ videoEncoder = VideoEncoderCoderMP4(width, height, width*height*4, File(getVideoFileAddress(time)))
+ videoEncoder?.apply {
+ OpenGLJniLib.buildVideoSurface(getInputSurface(), textureId, BaseApplication.context.assets)
+ OpenGLJniLib.magicVideoFilterChange(width,height)
+ if (filterType >= 0) {
+ OpenGLJniLib.setVideoFilterType(filterType)
+ }
+ start()
+ isReady.set(true)
+ }
+ }
+ }
+ audioEncoder = AudioRecordCoderAAC()
+ audioEncoder?.start(getAudioFileAddress(time))
+ }
+
+ fun stopRecord(){
+ recordThread.execute {
+ videoEncoder?.drainEncoder(true)
+ videoEncoder?.release()
+ videoEncoder = null
+ OpenGLJniLib.releaseVideoSurface()
+ isReady.set(false)
+ }
+ audioEncoder?.stop()
+ }
+
+ fun drawFrame(matrix:FloatArray,time:Long){
+ if(isReady.get()) {
+ recordThread.execute {
+ videoEncoder?.apply {
+ try {
+ drainEncoder(false)
+ }catch (e:Exception){
+ Log.e(TAG,e.toString())
+ }
+ OpenGLJniLib.magicVideoDraw(matrix, time)
+ }
+ }
+ }
+ }
+
+ private fun getVideoFileAddress(time:Long): String {
+ return if(Build.BRAND == "Xiaomi"){ // 小米手机
+ Environment.getExternalStorageDirectory().path +"/DCIM/Camera/"+time+".mp4"
+ }else{ // Meizu 、Oppo
+ Environment.getExternalStorageDirectory().path +"/DCIM/"+time+".mp4"
+ }
+ }
+
+ private fun getAudioFileAddress(time:Long): String {
+ return if(Build.BRAND == "Xiaomi"){ // 小米手机
+ Environment.getExternalStorageDirectory().path +"/DCIM/Camera/"+time+".aac"
+ }else{ // Meizu 、Oppo
+ Environment.getExternalStorageDirectory().path +"/DCIM/"+time+".pcm"
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/cangwang/magic/video/VideoEncoderCoder.kt b/app/src/main/java/com/cangwang/magic/video/VideoEncoderCoder.kt
new file mode 100644
index 0000000..40e6a5f
--- /dev/null
+++ b/app/src/main/java/com/cangwang/magic/video/VideoEncoderCoder.kt
@@ -0,0 +1,147 @@
+package com.cangwang.magic.video
+
+import android.media.MediaCodec
+import android.media.MediaCodecInfo
+import android.media.MediaFormat
+import android.util.Log
+import android.view.Surface
+import java.nio.ByteBuffer
+
+/**
+ * Created by cangwang on 2019.3.6
+ * 录制完整mp4短视频视轨
+ */
+class VideoEncoderCoder(width: Int, height: Int, bitRate: Int, muxer:MediaMuxerCoder?) {
+ companion object {
+ const val TAG = "VideoEncoderCoder"
+ const val MINE_TYPE = "video/avc"
+ const val FRAME_RATE = 30
+ const val IFRAME_INTERVAL = 5
+ }
+
+ private var mInputSurface:Surface
+ private var mMuxer:MediaMuxerCoder?=null
+ private var mEncoder:MediaCodec
+ private var mBufferInfo:MediaCodec.BufferInfo = MediaCodec.BufferInfo()
+
+ var encoderOutputBuffers:Array?=null
+
+ init {
+ val format = MediaFormat.createVideoFormat(MINE_TYPE,width,height)
+ format.setInteger(MediaFormat.KEY_COLOR_FORMAT,MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface)
+ format.setInteger(MediaFormat.KEY_BIT_RATE,bitRate)
+ format.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE)
+ format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL)
+ Log.d(TAG, "format: $format")
+ mEncoder = MediaCodec.createEncoderByType(MINE_TYPE)
+ mEncoder.configure(format,null,null,MediaCodec.CONFIGURE_FLAG_ENCODE)
+ mInputSurface = mEncoder.createInputSurface()
+
+ mMuxer = muxer
+// val track = mMuxer?.setVideoTrack(format)
+// Log.d(TAG, "videotrack: $track")
+ }
+
+ fun start(){
+ mEncoder.start()
+ }
+
+ fun stop(){
+ mEncoder.stop()
+ }
+
+ fun getInputSurface():Surface{
+ return mInputSurface
+ }
+
+ fun release(){
+ Log.d(TAG,"release encoder objects")
+ mEncoder.stop()
+ mEncoder.release()
+ }
+
+ /**
+ * 视频录制输入
+ * endOfStream 加入采集结束符
+ */
+ fun drainEncoder(endOfStream:Boolean){
+ val TIMEOUT_USEC = 10000L
+
+ if (endOfStream) {
+ Log.d(TAG, "sending EOS to encoder")
+ //只有视频流需要关闭输入标志
+ mEncoder.signalEndOfInputStream()
+ }
+
+ while (true) {
+ val encoderStatus = mEncoder.dequeueOutputBuffer(mBufferInfo, TIMEOUT_USEC)
+// Log.d(TAG, "drainEncoder($endOfStream),endcoderStatus($encoderStatus)")
+ if (encoderStatus == MediaCodec.INFO_TRY_AGAIN_LATER) {
+ // no output available yet
+ if (!endOfStream) {
+ break // out of while
+ } else {
+ Log.d(TAG, "no output available, spinning to await EOS")
+ }
+ } else if (encoderStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
+ // not expected for an encoder
+ encoderOutputBuffers = mEncoder.outputBuffers
+ } else if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+ //一定要在这个节点上获取fomart设置到混合器的视轨上
+ // should happen before receiving buffers, and should only happen once
+ if (mMuxer?.hasVideoTrack() == true) {
+ Log.d(TAG,"video format changed twice")
+ return
+ }
+ val newFormat = mEncoder.outputFormat
+ Log.d(TAG, "encoder output format changed: $newFormat")
+
+ // now that we have the Magic Goodies, start the muxer
+ val track = mMuxer?.setVideoTrack(newFormat)
+ Log.d(TAG, "videotrack: $track")
+ mMuxer?.start()
+ } else if (encoderStatus < 0) {
+ Log.w(TAG, "unexpected result from encoder.dequeueOutputBuffer: $encoderStatus")
+ // let's ignore it
+ } else {
+ encoderOutputBuffers = mEncoder.outputBuffers
+ if (encoderOutputBuffers != null) {
+ val encodedData = encoderOutputBuffers!![encoderStatus]
+
+ if (mBufferInfo.flags and MediaCodec.BUFFER_FLAG_CODEC_CONFIG != 0) {
+ // The codec config data was pulled out and fed to the muxer when we got
+ // the INFO_OUTPUT_FORMAT_CHANGED status. Ignore it.
+ Log.d(TAG, "ignoring BUFFER_FLAG_CODEC_CONFIG")
+ mBufferInfo.size = 0
+ }
+
+ if (mBufferInfo.size != 0) {
+ if (mMuxer?.isRecording() == false) {
+ Log.d(TAG,"muxer hasn't started")
+ break
+// throw RuntimeException("muxer hasn't started")
+ }
+
+ // adjust the ByteBuffer values to match BufferInfo (not needed?)
+ encodedData.position(mBufferInfo.offset)
+ encodedData.limit(mBufferInfo.offset + mBufferInfo.size)
+
+ mMuxer?.writeVideoData(encodedData, mBufferInfo)
+// Log.d(TAG, "sent " + mBufferInfo.size + " bytes to muxer, ts=" + mBufferInfo.presentationTimeUs)
+ }
+
+ mEncoder.releaseOutputBuffer(encoderStatus, false)
+
+ if (mBufferInfo.flags and MediaCodec.BUFFER_FLAG_END_OF_STREAM != 0) {
+ if (!endOfStream) {
+ Log.w(TAG, "reached end of stream unexpectedly")
+ } else {
+ Log.d(TAG, "end of stream reached")
+ }
+ break // out of while
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/cangwang/magic/video/VideoEncoderCoderMP4.kt b/app/src/main/java/com/cangwang/magic/video/VideoEncoderCoderMP4.kt
new file mode 100644
index 0000000..efda550
--- /dev/null
+++ b/app/src/main/java/com/cangwang/magic/video/VideoEncoderCoderMP4.kt
@@ -0,0 +1,145 @@
+package com.cangwang.magic.video
+
+import android.media.MediaCodec
+import android.media.MediaCodecInfo
+import android.media.MediaFormat
+import android.media.MediaMuxer
+import android.util.Log
+import android.view.Surface
+import java.io.File
+import java.lang.RuntimeException
+import java.nio.ByteBuffer
+
+/**
+ * Created by cangwang on 2019.3.6
+ * 单独MP4视频录制
+ */
+class VideoEncoderCoderMP4(width: Int, height: Int, bitRate: Int, outFile: File) {
+ companion object {
+ const val TAG = "VideoEncoderCoder"
+ const val MINE_TYPE = "video/avc"
+ const val FRAME_RATE = 30
+ const val IFRAME_INTERVAL = 5
+ }
+
+ private var mInputSurface:Surface
+ private var mMuxer:MediaMuxer
+ private var mEncoder:MediaCodec
+ private var mBufferInfo:MediaCodec.BufferInfo = MediaCodec.BufferInfo()
+ private var mTrackIndex = -1
+ private var mMuxerStarted = false
+ var encoderOutputBuffers:Array?=null
+
+ init {
+ val format = MediaFormat.createVideoFormat(MINE_TYPE,width,height)
+ format.setInteger(MediaFormat.KEY_COLOR_FORMAT,MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface)
+ format.setInteger(MediaFormat.KEY_BIT_RATE,bitRate)
+ format.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE)
+ format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL)
+ Log.d(TAG, "format: $format")
+ mEncoder = MediaCodec.createEncoderByType(MINE_TYPE)
+ mEncoder.configure(format,null,null,MediaCodec.CONFIGURE_FLAG_ENCODE)
+ mInputSurface = mEncoder.createInputSurface()
+ mMuxer = MediaMuxer(outFile.toString(),MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4)
+ mTrackIndex = -1
+ mMuxerStarted = false
+ }
+
+ fun start(){
+ mEncoder.start()
+ }
+
+ fun stop(){
+ mEncoder.stop()
+ }
+
+ fun getInputSurface():Surface{
+ return mInputSurface
+ }
+
+ fun release(){
+ Log.d(TAG,"release encoder objects")
+ mEncoder.stop()
+ mEncoder.release()
+
+ mMuxer.stop()
+ mMuxer.release()
+ }
+
+ fun drainEncoder(endOfStream:Boolean){
+ val TIMEOUT_USEC = 10000L
+
+ if (endOfStream) {
+ Log.d(TAG, "sending EOS to encoder")
+ mEncoder.signalEndOfInputStream()
+ }
+
+ while (true) {
+ val encoderStatus = mEncoder.dequeueOutputBuffer(mBufferInfo, TIMEOUT_USEC)
+ Log.d(TAG, "drainEncoder($endOfStream),endcoderStatus($encoderStatus)")
+ if (encoderStatus == MediaCodec.INFO_TRY_AGAIN_LATER) {
+ // no output available yet
+ if (!endOfStream) {
+ break // out of while
+ } else {
+ Log.d(TAG, "no output available, spinning to await EOS")
+ }
+ } else if (encoderStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
+ // not expected for an encoder
+ encoderOutputBuffers = mEncoder.outputBuffers
+ } else if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+ // should happen before receiving buffers, and should only happen once
+ if (mMuxerStarted) {
+ throw RuntimeException("format changed twice")
+ }
+ val newFormat = mEncoder.outputFormat
+ Log.d(TAG, "encoder output format changed: $newFormat")
+
+ // now that we have the Magic Goodies, start the muxer
+ mTrackIndex = mMuxer.addTrack(newFormat)
+ mMuxer.start()
+ mMuxerStarted = true
+ } else if (encoderStatus < 0) {
+ Log.w(TAG, "unexpected result from encoder.dequeueOutputBuffer: $encoderStatus")
+ // let's ignore it
+ } else {
+ encoderOutputBuffers = mEncoder.outputBuffers
+ if (encoderOutputBuffers != null) {
+ val encodedData = encoderOutputBuffers!![encoderStatus]
+
+ if (mBufferInfo.flags and MediaCodec.BUFFER_FLAG_CODEC_CONFIG != 0) {
+ // The codec config data was pulled out and fed to the muxer when we got
+ // the INFO_OUTPUT_FORMAT_CHANGED status. Ignore it.
+ Log.d(TAG, "ignoring BUFFER_FLAG_CODEC_CONFIG")
+ mBufferInfo.size = 0
+ }
+
+ if (mBufferInfo.size != 0) {
+ if (!mMuxerStarted) {
+ throw RuntimeException("muxer hasn't started")
+ }
+
+ // adjust the ByteBuffer values to match BufferInfo (not needed?)
+ encodedData.position(mBufferInfo.offset)
+ encodedData.limit(mBufferInfo.offset + mBufferInfo.size)
+
+ mMuxer.writeSampleData(mTrackIndex, encodedData, mBufferInfo)
+ Log.d(TAG, "sent " + mBufferInfo.size + " bytes to muxer, ts=" +
+ mBufferInfo.presentationTimeUs)
+ }
+
+ mEncoder.releaseOutputBuffer(encoderStatus, false)
+
+ if (mBufferInfo.flags and MediaCodec.BUFFER_FLAG_END_OF_STREAM != 0) {
+ if (!endOfStream) {
+ Log.w(TAG, "reached end of stream unexpectedly")
+ } else {
+ Log.d(TAG, "end of stream reached")
+ }
+ break // out of while
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/cangwang/magic/view/CameraFilterSurfaceCallback.kt b/app/src/main/java/com/cangwang/magic/view/CameraFilterSurfaceCallback.kt
index 6fe9fe2..6e1b464 100644
--- a/app/src/main/java/com/cangwang/magic/view/CameraFilterSurfaceCallback.kt
+++ b/app/src/main/java/com/cangwang/magic/view/CameraFilterSurfaceCallback.kt
@@ -1,6 +1,5 @@
package com.cangwang.magic.view
-
import android.annotation.SuppressLint
import android.graphics.SurfaceTexture
import android.hardware.Camera
@@ -12,24 +11,23 @@ import android.view.SurfaceHolder
import android.widget.Toast
import com.cangwang.magic.BaseApplication
import com.cangwang.magic.util.CameraHelper
-import com.cangwang.magic.util.OpenGLJniLib
+import com.cangwang.filter.util.OpenGLJniLib
import io.reactivex.Observable
import io.reactivex.ObservableOnSubscribe
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import java.io.IOException
-import java.util.*
import java.util.concurrent.Executors
/**
* Created by zjl on 2018/10/12.
*/
-class CameraFilterSurfaceCallback(camera:Camera?):SurfaceHolder.Callback{
+class CameraFilterSurfaceCallback(camera: Camera?) : SurfaceHolder.Callback {
private val mExecutor = Executors.newSingleThreadExecutor()
- private val TAG= CameraFilterSurfaceCallback::class.java.simpleName!!
- private var mSurfaceTexture:SurfaceTexture?=null
- private var mCamera=camera
+ private val TAG = CameraFilterSurfaceCallback::class.java.simpleName!!
+ private var mSurfaceTexture: SurfaceTexture? = null
+ private var mCamera = camera
private val mMatrix = FloatArray(16)
private var width = 0
private var height = 0
@@ -38,7 +36,7 @@ class CameraFilterSurfaceCallback(camera:Camera?):SurfaceHolder.Callback{
override fun surfaceChanged(holder: SurfaceHolder?, format: Int, width: Int, height: Int) {
this.width = width
this.height = height
- changeOpenGL(width,height)
+ changeOpenGL(width, height)
}
override fun surfaceDestroyed(holder: SurfaceHolder?) {
@@ -51,11 +49,11 @@ class CameraFilterSurfaceCallback(camera:Camera?):SurfaceHolder.Callback{
}
}
- fun initOpenGL(surface: Surface){
+ fun initOpenGL(surface: Surface) {
mExecutor.execute {
- val textureId = OpenGLJniLib.magicFilterCreate(surface,BaseApplication.context.assets)
+ val textureId = OpenGLJniLib.magicFilterCreate(surface, BaseApplication.context.assets)
// OpenGLJniLib.setFilterType(MagicFilterType.NONE.ordinal)
- if (textureId < 0){
+ if (textureId < 0) {
Log.e(TAG, "surfaceCreated init OpenGL ES failed!")
return@execute
}
@@ -64,14 +62,14 @@ class CameraFilterSurfaceCallback(camera:Camera?):SurfaceHolder.Callback{
try {
mCamera?.setPreviewTexture(mSurfaceTexture)
doStartPreview()
- }catch (e:IOException){
- Log.e(TAG,e.localizedMessage)
+ } catch (e: IOException) {
+ Log.e(TAG, e.localizedMessage)
releaseOpenGL()
}
}
}
- fun changeCamera(camera:Camera? ){
+ fun changeCamera(camera: Camera?) {
mExecutor.execute {
mCamera = camera
try {
@@ -84,50 +82,50 @@ class CameraFilterSurfaceCallback(camera:Camera?):SurfaceHolder.Callback{
}
}
- fun changeOpenGL(width:Int,height:Int){
+ fun changeOpenGL(width: Int, height: Int) {
mExecutor.execute {
- OpenGLJniLib.magicFilterChange(width,height)
+ OpenGLJniLib.magicFilterChange(width, height)
}
}
- fun drawOpenGL(){
+ fun drawOpenGL() {
mExecutor.execute {
mSurfaceTexture?.updateTexImage()
mSurfaceTexture?.getTransformMatrix(mMatrix)
- if (isTakePhoto){
- val photoAddress = if(Build.BRAND == "Xiaomi"){ // 小米手机
- Environment.getExternalStorageDirectory().path +"/DCIM/Camera/"+System.currentTimeMillis()+".png"
- }else{ // Meizu 、Oppo
- Environment.getExternalStorageDirectory().path +"/DCIM/"+System.currentTimeMillis()+".png"
+ if (isTakePhoto) {
+ val photoAddress = if (Build.BRAND == "Xiaomi") { // 小米手机
+ Environment.getExternalStorageDirectory().path + "/DCIM/Camera/" + System.currentTimeMillis() + ".png"
+ } else { // Meizu 、Oppo
+ Environment.getExternalStorageDirectory().path + "/DCIM/" + System.currentTimeMillis() + ".png"
}
- OpenGLJniLib.magicFilterDraw(mMatrix,photoAddress)
- }else {
- OpenGLJniLib.magicFilterDraw(mMatrix,"")
+ OpenGLJniLib.magicFilterDraw(mMatrix, photoAddress)
+ } else {
+ OpenGLJniLib.magicFilterDraw(mMatrix, "")
}
}
}
- fun releaseOpenGL(){
+ fun releaseOpenGL() {
mExecutor.execute {
OpenGLJniLib.magicFilterRelease()
mSurfaceTexture?.release()
- mSurfaceTexture=null
- mCamera =null
+ mSurfaceTexture = null
+ mCamera = null
}
}
- fun setFilterType(type:Int){
+ fun setFilterType(type: Int) {
mExecutor.execute {
OpenGLJniLib.setFilterType(type)
}
}
- fun doStartPreview(){
+ fun doStartPreview() {
mCamera?.startPreview()
- cameraFocus(width/2.0f,height/2.0f)
+ cameraFocus(width / 2.0f, height / 2.0f)
}
- fun cameraFocus(x:Float,y:Float){
+ fun cameraFocus(x: Float, y: Float) {
mCamera?.let {
it.cancelAutoFocus()
CameraHelper.setFocusMode(it, Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)
@@ -135,11 +133,11 @@ class CameraFilterSurfaceCallback(camera:Camera?):SurfaceHolder.Callback{
}
@SuppressLint("CheckResult")
- fun takePhoto(){
- val rootAddress = if(Build.BRAND == "Xiaomi"){ // 小米手机
- Environment.getExternalStorageDirectory().path +"/DCIM/Camera/"+System.currentTimeMillis()+".png"
- }else{ // Meizu 、Oppo
- Environment.getExternalStorageDirectory().path +"/DCIM/"+System.currentTimeMillis()+".png"
+ fun takePhoto() {
+ val rootAddress = if (Build.BRAND == "Xiaomi") { // 小米手机
+ Environment.getExternalStorageDirectory().path + "/DCIM/Camera/" + System.currentTimeMillis() + ".png"
+ } else { // Meizu 、Oppo
+ Environment.getExternalStorageDirectory().path + "/DCIM/" + System.currentTimeMillis() + ".png"
}
// mCamera?.stopPreview()
Observable.create(ObservableOnSubscribe {
@@ -147,15 +145,17 @@ class CameraFilterSurfaceCallback(camera:Camera?):SurfaceHolder.Callback{
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
-// mCamera?.startPreview()
- if (!it){
- Toast.makeText(BaseApplication.context,"save fail",Toast.LENGTH_SHORT).show()
- }else{
- Toast.makeText(BaseApplication.context,"save success",Toast.LENGTH_SHORT).show()
+ // mCamera?.startPreview()
+ if (!it) {
+ Toast.makeText(BaseApplication.context, "save fail", Toast.LENGTH_SHORT)
+ .show()
+ } else {
+ Toast.makeText(BaseApplication.context, "save success", Toast.LENGTH_SHORT)
+ .show()
}
- },{
-// mCamera?.startPreview()
- Log.e(TAG,it.toString())
+ }, {
+ // mCamera?.startPreview()
+ Log.e(TAG, it.toString())
})
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/cangwang/magic/view/CameraFilterSurfaceCallbackV2.kt b/app/src/main/java/com/cangwang/magic/view/CameraFilterSurfaceCallbackV2.kt
index 39d2fdd..fd0def4 100644
--- a/app/src/main/java/com/cangwang/magic/view/CameraFilterSurfaceCallbackV2.kt
+++ b/app/src/main/java/com/cangwang/magic/view/CameraFilterSurfaceCallbackV2.kt
@@ -3,6 +3,7 @@ package com.cangwang.magic.view
import android.annotation.SuppressLint
import android.graphics.SurfaceTexture
+import android.media.MediaRecorder
import android.os.Build
import android.os.Environment
import android.util.Log
@@ -11,14 +12,17 @@ import android.view.SurfaceHolder
import android.widget.Toast
import com.cangwang.magic.BaseApplication
import com.cangwang.magic.camera.CameraCompat
-import com.cangwang.magic.util.OpenGLJniLib
+import com.cangwang.filter.util.OpenGLJniLib
+import com.cangwang.magic.video.VideoEncoderCoderMP4
import io.reactivex.Observable
import io.reactivex.ObservableOnSubscribe
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
+import java.io.File
import java.io.IOException
import java.util.concurrent.Executors
+import java.util.concurrent.atomic.AtomicBoolean
/**
* Created by zjl on 2018/10/12.
@@ -28,12 +32,18 @@ class CameraFilterSurfaceCallbackV2(camera:CameraCompat?):SurfaceHolder.Callback
private val TAG= CameraFilterSurfaceCallbackV2::class.java.simpleName!!
private var mSurfaceTexture:SurfaceTexture?=null
+ private var mSurface:Surface?=null
private var mCamera=camera
private val mMatrix = FloatArray(16)
private var width = 0
private var height = 0
private var isTakePhoto = false
+ private var mMediaRecorder:MediaRecorder?=null
+ private var isRecordVideo = AtomicBoolean()
+ private var previewSurface:Surface?=null
+ private var videoEncoder:VideoEncoderCoderMP4 ?=null
+
override fun surfaceChanged(holder: SurfaceHolder?, format: Int, width: Int, height: Int) {
this.width = width
this.height = height
@@ -47,6 +57,7 @@ class CameraFilterSurfaceCallbackV2(camera:CameraCompat?):SurfaceHolder.Callback
override fun surfaceCreated(holder: SurfaceHolder?) {
holder?.let {
+ previewSurface = it.surface
initOpenGL(it.surface)
}
}
@@ -61,6 +72,7 @@ class CameraFilterSurfaceCallbackV2(camera:CameraCompat?):SurfaceHolder.Callback
}
mSurfaceTexture = SurfaceTexture(textureId)
mSurfaceTexture?.setOnFrameAvailableListener { drawOpenGL() }
+ mSurface = Surface(mSurfaceTexture)
try {
mSurfaceTexture?.let {
mCamera?.setSurfaceTexture(it)
@@ -73,6 +85,41 @@ class CameraFilterSurfaceCallbackV2(camera:CameraCompat?):SurfaceHolder.Callback
}
}
+ fun startRecordVideo(){
+ if (isRecordVideo.get()){
+ return
+ }
+
+ if (mSurface!=null && width>0 && height>0)
+ videoEncoder = VideoEncoderCoderMP4(width,height,1000000, File(getVideoFileAddress()))
+
+ videoEncoder?.start()
+ isRecordVideo.set(true)
+ }
+
+ fun stopRecordVideo(){
+ videoEncoder?.stop()
+ }
+
+ fun resumeRecordVideo(){
+
+ }
+
+ fun isRecording():Boolean{
+ return isRecordVideo.get()
+ }
+
+ fun releaseRecordVideo(){
+ mExecutor.execute {
+ if (isRecordVideo.get()) {
+ videoEncoder?.drainEncoder(true)
+ videoEncoder?.release()
+ videoEncoder = null
+ isRecordVideo.set(false)
+ }
+ }
+ }
+
fun changeCamera(camera:CameraCompat? ){
mExecutor.execute {
mCamera = camera
@@ -99,16 +146,13 @@ class CameraFilterSurfaceCallbackV2(camera:CameraCompat?):SurfaceHolder.Callback
mSurfaceTexture?.updateTexImage()
mSurfaceTexture?.getTransformMatrix(mMatrix)
if (isTakePhoto){
- val photoAddress = if(Build.BRAND == "Xiaomi"){ // 小米手机
- Environment.getExternalStorageDirectory().path +"/DCIM/Camera/"+System.currentTimeMillis()+".png"
- }else{ // Meizu 、Oppo
- Environment.getExternalStorageDirectory().path +"/DCIM/"+System.currentTimeMillis()+".png"
- }
+ val photoAddress = getImageFileAddress()
OpenGLJniLib.magicFilterDraw(mMatrix,photoAddress)
isTakePhoto =false
}else {
OpenGLJniLib.magicFilterDraw(mMatrix,"")
}
+ videoEncoder?.drainEncoder(false)
}
}
@@ -128,16 +172,22 @@ class CameraFilterSurfaceCallbackV2(camera:CameraCompat?):SurfaceHolder.Callback
}
fun doStartPreview(){
- mCamera?.startPreview()
+ mCamera?.startPreview(object :CameraCompat.CameraStateCallBack{
+ override fun onConfigured() {
+ if (isRecordVideo.get()){
+ mMediaRecorder?.start()
+ }
+ }
+
+ override fun onConfigureFailed() {
+
+ }
+ })
}
@SuppressLint("CheckResult")
fun takePhoto(){
- val rootAddress = if(Build.BRAND == "Xiaomi"){ // 小米手机
- Environment.getExternalStorageDirectory().path +"/DCIM/Camera/"+System.currentTimeMillis()+".png"
- }else{ // Meizu 、Oppo
- Environment.getExternalStorageDirectory().path +"/DCIM/"+System.currentTimeMillis()+".png"
- }
+ val rootAddress= getImageFileAddress()
// mCamera?.stopPreview()
Observable.create(ObservableOnSubscribe {
it.onNext(OpenGLJniLib.savePhoto(rootAddress))
@@ -155,4 +205,20 @@ class CameraFilterSurfaceCallbackV2(camera:CameraCompat?):SurfaceHolder.Callback
Log.e(TAG,it.toString())
})
}
+
+ fun getVideoFileAddress(): String {
+ return if(Build.BRAND == "Xiaomi"){ // 小米手机
+ Environment.getExternalStorageDirectory().path +"/DCIM/Camera/"+System.currentTimeMillis()+".mp4"
+ }else{ // Meizu 、Oppo
+ Environment.getExternalStorageDirectory().path +"/DCIM/"+System.currentTimeMillis()+".mp4"
+ }
+ }
+
+ fun getImageFileAddress():String{
+ return if(Build.BRAND == "Xiaomi"){ // 小米手机
+ Environment.getExternalStorageDirectory().path +"/DCIM/Camera/"+System.currentTimeMillis()+".png"
+ }else{ // Meizu 、Oppo
+ Environment.getExternalStorageDirectory().path +"/DCIM/"+System.currentTimeMillis()+".png"
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/cangwang/magic/view/CameraFilterSurfaceCallbackV3.kt b/app/src/main/java/com/cangwang/magic/view/CameraFilterSurfaceCallbackV3.kt
new file mode 100644
index 0000000..a7300b6
--- /dev/null
+++ b/app/src/main/java/com/cangwang/magic/view/CameraFilterSurfaceCallbackV3.kt
@@ -0,0 +1,216 @@
+package com.cangwang.magic.view
+
+import android.annotation.SuppressLint
+import android.graphics.SurfaceTexture
+import android.os.Build
+import android.os.Environment
+import android.util.Log
+import android.view.Surface
+import android.view.SurfaceHolder
+import android.widget.Toast
+import com.cangwang.magic.BaseApplication
+import com.cangwang.magic.camera.CameraCompat
+import com.cangwang.filter.util.OpenGLJniLib
+import com.cangwang.magic.video.TextureMovieEncoder
+import io.reactivex.Observable
+import io.reactivex.ObservableOnSubscribe
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.schedulers.Schedulers
+import java.io.IOException
+
+import java.util.concurrent.Executors
+import java.util.concurrent.atomic.AtomicBoolean
+
+/**
+ * Created by zjl on 2018/10/12.
+ */
+class CameraFilterSurfaceCallbackV3(camera: CameraCompat?,filterType:Int) : SurfaceHolder.Callback {
+ private val mExecutor = Executors.newSingleThreadExecutor()
+
+ private val TAG = CameraFilterSurfaceCallbackV3::class.java.simpleName!!
+ private var mSurfaceTexture: SurfaceTexture? = null
+ private var mSurface: Surface? = null
+ private var mCamera = camera
+ private val mMatrix = FloatArray(16)
+ private var width = 0
+ private var height = 0
+ private var isTakePhoto = false
+ private var textureId: Int = -1
+
+ private var isRecordVideo = AtomicBoolean()
+ private var previewSurface: Surface? = null
+ private var recordStatus = RECORD_IDLE
+ private var filterType: Int = 0
+ private var movieEncoder: TextureMovieEncoder = TextureMovieEncoder()
+ init {
+ this.filterType = filterType
+ }
+
+ companion object {
+ val RECORD_IDLE = 0
+ val RECORD_START = 1
+ val RECORD_RECORDING = 2
+ val RECORD_STOP = 3
+ }
+
+ override fun surfaceChanged(holder: SurfaceHolder?, format: Int, width: Int, height: Int) {
+ Log.d(TAG,"surfaceChanged")
+ this.width = width
+ this.height = height
+ changeOpenGL(width, height)
+ setFilterType(filterType)
+ }
+
+ override fun surfaceDestroyed(holder: SurfaceHolder?) {
+ Log.d(TAG,"surfaceDestroyed")
+ releaseOpenGL()
+ }
+
+ override fun surfaceCreated(holder: SurfaceHolder?) {
+ Log.d(TAG,"surfaceCreated")
+ holder?.let {
+ previewSurface = it.surface
+ initOpenGL(it.surface)
+ mSurface = it.surface
+ }
+ }
+
+ fun initOpenGL(surface: Surface) {
+ mExecutor.execute {
+ textureId = OpenGLJniLib.magicFilterCreate(surface, BaseApplication.context.assets)
+ if (textureId < 0) {
+ Log.e(TAG, "surfaceCreated init OpenGL ES failed!")
+ return@execute
+ }
+ mSurfaceTexture = SurfaceTexture(textureId)
+ mSurfaceTexture?.setOnFrameAvailableListener { drawOpenGL() }
+ try {
+ mSurfaceTexture?.let {
+ mCamera?.setSurfaceTexture(it)
+ }
+ doStartPreview()
+ } catch (e: IOException) {
+ Log.e(TAG, e.localizedMessage)
+ releaseOpenGL()
+ }
+ }
+ }
+
+ fun startRecordVideo() {
+ recordStatus = RECORD_START
+ }
+
+ fun isRecording(): Boolean {
+ return isRecordVideo.get()
+ }
+
+ fun releaseRecordVideo() {
+ recordStatus = RECORD_STOP
+ }
+
+ fun changeOpenGL(width: Int, height: Int) {
+ mExecutor.execute {
+ OpenGLJniLib.magicFilterChange(width, height)
+ }
+ }
+
+ fun drawOpenGL() {
+ mExecutor.execute {
+ mSurfaceTexture?.apply {
+ updateTexImage()
+
+ if (recordStatus == RECORD_START) {
+ movieEncoder.startRecord(width, height, textureId, filterType)
+ isRecordVideo.set(true)
+ recordStatus = RECORD_RECORDING
+ } else if (recordStatus == RECORD_STOP) {
+ if (isRecordVideo.get()) {
+ movieEncoder.stopRecord()
+ isRecordVideo.set(false)
+ recordStatus = RECORD_IDLE
+ }
+ }
+
+ getTransformMatrix(mMatrix)
+ if (isTakePhoto) {
+ val photoAddress = getImageFileAddress()
+ OpenGLJniLib.magicFilterDraw(mMatrix, photoAddress)
+ isTakePhoto = false
+ } else {
+ OpenGLJniLib.magicFilterDraw(mMatrix, "")
+ }
+
+ movieEncoder.drawFrame(mMatrix, timestamp)
+ }
+ }
+ }
+
+ fun releaseOpenGL() {
+ mExecutor.execute {
+ mCamera?.stopPreview(true)
+ OpenGLJniLib.magicFilterRelease()
+ mSurfaceTexture?.release()
+ mSurfaceTexture = null
+ mCamera = null
+ if(movieEncoder.isReady.get())
+ movieEncoder.stopRecord()
+ }
+ }
+
+ fun setFilterType(type: Int) {
+ mExecutor.execute {
+ filterType = type
+ OpenGLJniLib.setFilterType(type)
+ }
+ }
+
+ fun doStartPreview() {
+ //开始预览
+ mCamera?.startPreview(object : CameraCompat.CameraStateCallBack {
+ override fun onConfigured() {
+
+ }
+
+ override fun onConfigureFailed() {
+
+ }
+ })
+ }
+
+ @SuppressLint("CheckResult")
+ fun takePhoto() {
+ val rootAddress = getImageFileAddress()
+// mCamera?.stopPreview()
+ Observable.create(ObservableOnSubscribe {
+ it.onNext(OpenGLJniLib.savePhoto(rootAddress))
+ }).subscribeOn(Schedulers.from(mExecutor))
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe({
+ // mCamera?.startPreview()
+ if (!it) {
+ Toast.makeText(BaseApplication.context, "save fail", Toast.LENGTH_SHORT).show()
+ } else {
+ Toast.makeText(BaseApplication.context, "save success", Toast.LENGTH_SHORT).show()
+ }
+ }, {
+ // mCamera?.startPreview()
+ Log.e(TAG, it.toString())
+ })
+ }
+
+ fun getVideoFileAddress(): String {
+ return if (Build.BRAND == "Xiaomi") { // 小米手机
+ Environment.getExternalStorageDirectory().path + "/DCIM/Camera/" + System.currentTimeMillis() + ".mp4"
+ } else { // Meizu 、Oppo
+ Environment.getExternalStorageDirectory().path + "/DCIM/" + System.currentTimeMillis() + ".mp4"
+ }
+ }
+
+ fun getImageFileAddress(): String {
+ return if (Build.BRAND == "Xiaomi") { // 小米手机
+ Environment.getExternalStorageDirectory().path + "/DCIM/Camera/" + System.currentTimeMillis() + ".png"
+ } else { // Meizu 、Oppo
+ Environment.getExternalStorageDirectory().path + "/DCIM/" + System.currentTimeMillis() + ".png"
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/cangwang/magic/view/CameraSurfaceCallback.kt b/app/src/main/java/com/cangwang/magic/view/CameraSurfaceCallback.kt
index 23f65e0..73aa9d3 100644
--- a/app/src/main/java/com/cangwang/magic/view/CameraSurfaceCallback.kt
+++ b/app/src/main/java/com/cangwang/magic/view/CameraSurfaceCallback.kt
@@ -1,6 +1,5 @@
package com.cangwang.magic.view
-
import android.graphics.SurfaceTexture
import android.hardware.Camera
import android.util.Log
@@ -8,19 +7,19 @@ import android.view.Surface
import android.view.SurfaceHolder
import com.cangwang.magic.BaseApplication
import com.cangwang.magic.util.CameraHelper
-import com.cangwang.magic.util.OpenGLJniLib
+import com.cangwang.filter.util.OpenGLJniLib
import java.io.IOException
import java.util.concurrent.Executors
/**
* Created by zjl on 2018/10/12.
*/
-class CameraSurfaceCallback(camera:Camera?):SurfaceHolder.Callback{
+class CameraSurfaceCallback(camera: Camera?) : SurfaceHolder.Callback {
private val mExecutor = Executors.newSingleThreadExecutor()
- private val TAG= CameraSurfaceCallback::class.java.simpleName!!
- private var mSurfaceTexture:SurfaceTexture?=null
- private val mCamera=camera
+ private val TAG = CameraSurfaceCallback::class.java.simpleName!!
+ private var mSurfaceTexture: SurfaceTexture? = null
+ private val mCamera = camera
private val mMatrix = FloatArray(16)
private var width = 0
private var height = 0
@@ -29,7 +28,7 @@ class CameraSurfaceCallback(camera:Camera?):SurfaceHolder.Callback{
this.width = width
this.height = height
holder?.let {
- initOpenGL(it.surface,width,height)
+ initOpenGL(it.surface, width, height)
}
}
@@ -38,14 +37,14 @@ class CameraSurfaceCallback(camera:Camera?):SurfaceHolder.Callback{
}
override fun surfaceCreated(holder: SurfaceHolder?) {
-
}
- fun initOpenGL(surface: Surface, width: Int, height: Int){
+ fun initOpenGL(surface: Surface, width: Int, height: Int) {
mExecutor.execute {
//获取纹理id
- val textureId = OpenGLJniLib.magicBaseInit(surface,width,height,BaseApplication.context.assets)
- if (textureId < 0){
+ val textureId = OpenGLJniLib.magicBaseInit(surface, width, height,
+ BaseApplication.context.assets)
+ if (textureId < 0) {
Log.e(TAG, "surfaceCreated init OpenGL ES failed!")
return@execute
}
@@ -58,14 +57,14 @@ class CameraSurfaceCallback(camera:Camera?):SurfaceHolder.Callback{
mCamera?.setPreviewTexture(mSurfaceTexture)
//开始摄像头采样
doStartPreview()
- }catch (e:IOException){
- Log.e(TAG,e.localizedMessage)
+ } catch (e: IOException) {
+ Log.e(TAG, e.localizedMessage)
releaseOpenGL()
}
}
}
- fun drawOpenGL(){
+ fun drawOpenGL() {
mExecutor.execute {
//重新获取纹理图像
mSurfaceTexture?.updateTexImage()
@@ -76,20 +75,20 @@ class CameraSurfaceCallback(camera:Camera?):SurfaceHolder.Callback{
}
}
- fun releaseOpenGL(){
+ fun releaseOpenGL() {
mExecutor.execute {
mSurfaceTexture?.release()
- mSurfaceTexture=null
+ mSurfaceTexture = null
OpenGLJniLib.magicBaseRelease()
}
}
- fun doStartPreview(){
+ fun doStartPreview() {
mCamera?.startPreview()
- cameraFocus(width/2.0f,height/2.0f)
+ cameraFocus(width / 2.0f, height / 2.0f)
}
- fun cameraFocus(x:Float,y:Float){
+ fun cameraFocus(x: Float, y: Float) {
mCamera?.let {
it.cancelAutoFocus()
CameraHelper.setFocusMode(it, Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)
diff --git a/app/src/main/java/com/cangwang/magic/view/ImageFilterSurfaceCallback.kt b/app/src/main/java/com/cangwang/magic/view/ImageFilterSurfaceCallback.kt
index afe317d..882b9ad 100644
--- a/app/src/main/java/com/cangwang/magic/view/ImageFilterSurfaceCallback.kt
+++ b/app/src/main/java/com/cangwang/magic/view/ImageFilterSurfaceCallback.kt
@@ -10,7 +10,7 @@ import android.view.SurfaceHolder
import android.widget.Toast
import com.cangwang.magic.BaseApplication
import com.cangwang.magic.util.ExifUtil
-import com.cangwang.magic.util.OpenGLJniLib
+import com.cangwang.filter.util.OpenGLJniLib
import io.reactivex.Observable
import io.reactivex.ObservableOnSubscribe
import io.reactivex.android.schedulers.AndroidSchedulers
@@ -21,21 +21,27 @@ import java.util.concurrent.Executors
/**
* Created by zjl on 2018/10/12.
*/
-class ImageFilterSurfaceCallback(path:String):SurfaceHolder.Callback{
+class ImageFilterSurfaceCallback(path: String, filterType: Int) : SurfaceHolder.Callback {
private val mExecutor = Executors.newSingleThreadExecutor()
- private val TAG= ImageFilterSurfaceCallback::class.java.simpleName!!
- private var mSurfaceTexture:SurfaceTexture?=null
+ private val TAG = ImageFilterSurfaceCallback::class.java.simpleName!!
+ private var mSurfaceTexture: SurfaceTexture? = null
private val mMatrix = FloatArray(16)
private var width = 0
private var height = 0
private var isTakePhoto = false
private val imagePath = path
+ private var filterType = 0
+
+ init {
+ this.filterType = filterType
+ }
override fun surfaceChanged(holder: SurfaceHolder?, format: Int, width: Int, height: Int) {
this.width = width
this.height = height
- changeOpenGL(width,height)
+ changeOpenGL(width, height)
+ setFilterType(filterType)
}
override fun surfaceDestroyed(holder: SurfaceHolder?) {
@@ -48,10 +54,12 @@ class ImageFilterSurfaceCallback(path:String):SurfaceHolder.Callback{
}
}
- private fun initOpenGL(surface: Surface){
+ private fun initOpenGL(surface: Surface) {
mExecutor.execute {
- val textureId = OpenGLJniLib.magicImageFilterCreate(surface,BaseApplication.context.assets,imagePath,ExifUtil.getExifOrientation(imagePath))
- if (textureId < 0){
+ val textureId =
+ OpenGLJniLib.magicImageFilterCreate(surface, BaseApplication.context.assets,
+ imagePath, ExifUtil.getExifOrientation(imagePath))
+ if (textureId < 0) {
Log.e(TAG, "surfaceCreated init OpenGL ES failed!")
return@execute
}
@@ -63,65 +71,66 @@ class ImageFilterSurfaceCallback(path:String):SurfaceHolder.Callback{
}
}
-
- fun changeOpenGL(width:Int,height:Int){
+ fun changeOpenGL(width: Int, height: Int) {
mExecutor.execute {
- OpenGLJniLib.magicImageFilterChange(width,height)
- OpenGLJniLib.magicImageFilterDraw(mMatrix,"")
+ OpenGLJniLib.magicImageFilterChange(width, height)
+ OpenGLJniLib.magicImageFilterDraw(mMatrix, "")
}
}
- fun drawOpenGL(){
+ fun drawOpenGL() {
mExecutor.execute {
mSurfaceTexture?.updateTexImage()
// mSurfaceTexture?.getTransformMatrix(mMatrix)
- if (isTakePhoto){
- val photoAddress = if(Build.BRAND == "Xiaomi"){ // 小米手机
- Environment.getExternalStorageDirectory().path +"/DCIM/Camera/"+System.currentTimeMillis()+".png"
- }else{ // Meizu 、Oppo
- Environment.getExternalStorageDirectory().path +"/DCIM/"+System.currentTimeMillis()+".png"
+ if (isTakePhoto) {
+ val photoAddress = if (Build.BRAND == "Xiaomi") { // 小米手机
+ Environment.getExternalStorageDirectory().path + "/DCIM/Camera/" + System.currentTimeMillis() + ".png"
+ } else { // Meizu 、Oppo
+ Environment.getExternalStorageDirectory().path + "/DCIM/" + System.currentTimeMillis() + ".png"
}
- OpenGLJniLib.magicImageFilterDraw(mMatrix,photoAddress)
- }else {
- OpenGLJniLib.magicImageFilterDraw(mMatrix,"")
+ OpenGLJniLib.magicImageFilterDraw(mMatrix, photoAddress)
+ } else {
+ OpenGLJniLib.magicImageFilterDraw(mMatrix, "")
}
}
}
- private fun releaseOpenGL(){
+ fun releaseOpenGL() {
mExecutor.execute {
OpenGLJniLib.magicImageFilterRelease()
mSurfaceTexture?.release()
- mSurfaceTexture=null
+ mSurfaceTexture = null
}
}
- fun setFilterType(type:Int){
+ fun setFilterType(type: Int) {
mExecutor.execute {
OpenGLJniLib.setImageFilterType(type)
- OpenGLJniLib.magicImageFilterDraw(mMatrix,"")
+ OpenGLJniLib.magicImageFilterDraw(mMatrix, "")
}
}
@SuppressLint("CheckResult")
- fun saveImage(){
- val rootAddress = if(Build.BRAND == "Xiaomi"){ // 小米手机
- Environment.getExternalStorageDirectory().path +"/DCIM/Camera/"+System.currentTimeMillis()+".png"
- }else{ // Meizu 、Oppo
- Environment.getExternalStorageDirectory().path +"/DCIM/"+System.currentTimeMillis()+".png"
+ fun saveImage() {
+ val rootAddress = if (Build.BRAND == "Xiaomi") { // 小米手机
+ Environment.getExternalStorageDirectory().path + "/DCIM/Camera/" + System.currentTimeMillis() + ".png"
+ } else { // Meizu 、Oppo
+ Environment.getExternalStorageDirectory().path + "/DCIM/" + System.currentTimeMillis() + ".png"
}
Observable.create(ObservableOnSubscribe {
it.onNext(OpenGLJniLib.saveImage(rootAddress))
}).subscribeOn(Schedulers.from(mExecutor))
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
- if (!it){
- Toast.makeText(BaseApplication.context,"save fail",Toast.LENGTH_SHORT).show()
- }else{
- Toast.makeText(BaseApplication.context,"save success",Toast.LENGTH_SHORT).show()
+ if (!it) {
+ Toast.makeText(BaseApplication.context, "save fail", Toast.LENGTH_SHORT)
+ .show()
+ } else {
+ Toast.makeText(BaseApplication.context, "save success", Toast.LENGTH_SHORT)
+ .show()
}
- },{
- Log.e(TAG,it.toString())
+ }, {
+ Log.e(TAG, it.toString())
})
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/cangwang/magic/view/MagicCameraView.kt b/app/src/main/java/com/cangwang/magic/view/MagicCameraView.kt
index c01528f..f26befc 100644
--- a/app/src/main/java/com/cangwang/magic/view/MagicCameraView.kt
+++ b/app/src/main/java/com/cangwang/magic/view/MagicCameraView.kt
@@ -3,7 +3,7 @@
//import android.content.Context
//import android.opengl.GLSurfaceView
//import android.util.AttributeSet
-//import com.cangwang.magic.util.OpenGLJniLib
+//import OpenGLJniLib
//import javax.microedition.khronos.egl.EGLConfig
//import javax.microedition.khronos.opengles.GL10
//
diff --git a/app/src/main/res/drawable-xhdpi/glitch.png b/app/src/main/res/drawable-xhdpi/glitch.png
new file mode 100644
index 0000000..8fbce79
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/glitch.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_fouces.png b/app/src/main/res/drawable-xhdpi/ic_fouces.png
new file mode 100644
index 0000000..ef73e23
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_fouces.png differ
diff --git a/app/src/main/res/drawable-xhdpi/scale.png b/app/src/main/res/drawable-xhdpi/scale.png
new file mode 100644
index 0000000..7f9266a
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/scale.png differ
diff --git a/app/src/main/res/drawable-xhdpi/shade.png b/app/src/main/res/drawable-xhdpi/shade.png
new file mode 100644
index 0000000..a49ebd6
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/shade.png differ
diff --git a/app/src/main/res/drawable-xhdpi/shinewhite.png b/app/src/main/res/drawable-xhdpi/shinewhite.png
new file mode 100644
index 0000000..edc3b3f
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/shinewhite.png differ
diff --git a/app/src/main/res/drawable-xhdpi/soulout.png b/app/src/main/res/drawable-xhdpi/soulout.png
new file mode 100644
index 0000000..8a0a038
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/soulout.png differ
diff --git a/app/src/main/res/drawable-xhdpi/verigo.png b/app/src/main/res/drawable-xhdpi/verigo.png
new file mode 100644
index 0000000..a5bf615
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/verigo.png differ
diff --git a/app/src/main/res/drawable/video_record_seekbar_thumb_transparent.xml b/app/src/main/res/drawable/video_record_seekbar_thumb_transparent.xml
new file mode 100644
index 0000000..069e3a7
--- /dev/null
+++ b/app/src/main/res/drawable/video_record_seekbar_thumb_transparent.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/video_record_seekbar_transparent.xml b/app/src/main/res/drawable/video_record_seekbar_transparent.xml
new file mode 100644
index 0000000..1b19600
--- /dev/null
+++ b/app/src/main/res/drawable/video_record_seekbar_transparent.xml
@@ -0,0 +1,26 @@
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_camera.xml b/app/src/main/res/layout/activity_camera.xml
index efa07fc..ddbffab 100644
--- a/app/src/main/res/layout/activity_camera.xml
+++ b/app/src/main/res/layout/activity_camera.xml
@@ -19,18 +19,40 @@
android:orientation="horizontal"
android:background="@android:color/transparent">
+
+
+
diff --git a/app/src/main/res/layout/activity_camera_sample.xml b/app/src/main/res/layout/activity_camera_sample.xml
new file mode 100755
index 0000000..b3565b6
--- /dev/null
+++ b/app/src/main/res/layout/activity_camera_sample.xml
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index ff8de15..9d3b407 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -27,6 +27,11 @@
android:layout_below="@+id/button_filter"
android:layout_marginTop="10dp" />
-
-
+
diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml
index 20a085c..74ed294 100644
--- a/app/src/main/res/values-zh-rCN/strings.xml
+++ b/app/src/main/res/values-zh-rCN/strings.xml
@@ -7,6 +7,7 @@
放大
闪白
幻觉
+ 三重镜像
白猫
黑猫
浪漫
diff --git a/app/src/main/res/values/feature_names.xml b/app/src/main/res/values/feature_names.xml
new file mode 100644
index 0000000..5b98c5a
--- /dev/null
+++ b/app/src/main/res/values/feature_names.xml
@@ -0,0 +1,20 @@
+
+
+
+
+ play
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index df6df18..2594f92 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -6,6 +6,7 @@
Glitch
Scale
ShineWhite
+ ThreeWin
Verigo
Amaro
Brannan
@@ -63,4 +64,5 @@
Sharpness
Bright
Hue
+ Magic Player
diff --git a/base/.gitignore b/base/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/base/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/base/build.gradle b/base/build.gradle
new file mode 100644
index 0000000..25d512f
--- /dev/null
+++ b/base/build.gradle
@@ -0,0 +1,46 @@
+apply plugin: 'com.android.library'
+apply plugin: 'kotlin-kapt'
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-android-extensions'
+
+android {
+ compileSdkVersion 28
+
+ defaultConfig {
+ minSdkVersion 21
+ targetSdkVersion 28
+ versionCode 1
+ versionName "1.0"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+ compileOptions {
+ targetCompatibility 1.8
+ sourceCompatibility 1.8
+ }
+}
+
+dependencies {
+ api fileTree(dir: 'libs', include: ['*.jar'])
+
+ implementation 'com.android.support:appcompat-v7:28.0.0'
+ implementation 'com.android.support:design:28.0.0'
+ api ("com.alibaba:arouter-api:$arouter_api_version",{
+ exclude group: 'com.android.support'
+ })
+ api 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.1'
+ api 'org.jetbrains.kotlinx:kotlinx-coroutines-android:0.22.5'
+ kapt "com.alibaba:arouter-compiler:$arouter_compiler_version"
+}
+
+kapt {
+ arguments {
+ arg("AROUTER_MODULE_NAME", project.getName())
+ }
+}
+
diff --git a/base/proguard-rules.pro b/base/proguard-rules.pro
new file mode 100644
index 0000000..f1b4245
--- /dev/null
+++ b/base/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/base/src/main/AndroidManifest.xml b/base/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..371c8bd
--- /dev/null
+++ b/base/src/main/AndroidManifest.xml
@@ -0,0 +1,2 @@
+
diff --git a/base/src/main/res/values/strings.xml b/base/src/main/res/values/strings.xml
new file mode 100644
index 0000000..b55c9ae
--- /dev/null
+++ b/base/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ base
+
diff --git a/build.gradle b/build.gradle
index d7be872..1b1ecc3 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,14 +1,14 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
- ext.kotlin_version = '1.2.0'
+ ext.kotlin_version = '1.3.20'
repositories {
google()
jcenter()
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.0.1'
- classpath "com.android.tools.build:gradle-experimental:0.11.1"
+ classpath 'com.android.tools.build:gradle:3.3.2'
+// classpath 'com.android.tools.build:gradle-experimental:3.3.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
diff --git a/filter/.gitignore b/filter/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/filter/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/filter/CMakeLists.txt b/filter/CMakeLists.txt
new file mode 100644
index 0000000..ab862d7
--- /dev/null
+++ b/filter/CMakeLists.txt
@@ -0,0 +1,188 @@
+# For more information about using CMake with Android Studio, read the
+# documentation: https://d.android.com/studio/projects/add-native-code.html
+
+# Sets the minimum version of CMake required to build the native library.
+
+cmake_minimum_required(VERSION 3.4.1)
+
+# Creates and names a library, sets it as either STATIC
+# or SHARED, and provides the relative paths to its source code.
+# You can define multiple libraries, and CMake builds them for you.
+# Gradle automatically packages shared libraries with your APK.
+
+include_directories(${CMAKE_SOURCE_DIR} src/main/cpp)
+
+set(SRC_DIR src/main/cpp)
+#file(GLOB_RECURSE CPP_SRCS "${SRC_DIR}/*.cpp") #指定当前目录下的所有.cpp文件(包括子目录)
+file(GLOB_RECURSE CPP_SRCS
+ "${SRC_DIR}/bitmap/*.cpp"
+ "${SRC_DIR}/camera/*.cpp"
+ "${SRC_DIR}/egl/*.cpp"
+ "${SRC_DIR}/filter/*.cpp"
+ "${SRC_DIR}/image/*.cpp"
+ "${SRC_DIR}/utils/*.cpp"
+ "${SRC_DIR}/video/*.cpp"
+ "${SRC_DIR}/magicjni.cpp")
+
+add_library( # Sets the name of the library.
+ magicjni
+
+ # Sets the library as a shared library.
+ SHARED
+
+ # Provides a relative path to your source file(s).
+ ${CPP_SRCS})
+
+
+#file(GLOB_RECURSE Files_CPP
+# "${SRC_DIR}/effect/*.cpp"
+# "${SRC_DIR}/source/*.cpp"
+# "${SRC_DIR}/GPUImagexJNI.cpp")
+#
+#add_library( # Sets the name of the library.
+# GPUImage-x
+#
+# # Sets the library as a shared library.
+# SHARED
+#
+# # Provides a relative path to your source file(s).
+# ${Files_CPP})
+
+add_library( GPUImage-x
+ SHARED
+ src/main/cpp/source/Ref.cpp
+ src/main/cpp/source/util.cpp
+ src/main/cpp/source/FramebufferCache.cpp
+ src/main/cpp/source/Framebuffer.cpp
+ src/main/cpp/source/GLProgram.cpp
+ src/main/cpp/source/Context.cpp
+ src/main/cpp/source/math.cpp
+ src/main/cpp/GPUImagexJNI.cpp
+ src/main/cpp/source/Source.cpp
+ src/main/cpp/source/SourceImage.cpp
+ src/main/cpp/source/SourceCamera.cpp
+ src/main/cpp/source/Target.cpp
+ src/main/cpp/source/TargetView.cpp
+ src/main/cpp/effect/Filter.cpp
+ src/main/cpp/effect/FilterGroup.cpp
+ src/main/cpp/effect/BrightnessFilter.cpp
+ src/main/cpp/effect/ColorInvertFilter.cpp
+ src/main/cpp/effect/GrayscaleFilter.cpp
+ src/main/cpp/effect/GaussianBlurFilter.cpp
+ src/main/cpp/effect/GaussianBlurMonoFilter.cpp
+ src/main/cpp/effect/NearbySampling3x3Filter.cpp
+ src/main/cpp/effect/DirectionalSobelEdgeDetectionFilter.cpp
+ src/main/cpp/effect/DirectionalNonMaximumSuppressionFilter.cpp
+ src/main/cpp/effect/WeakPixelInclusionFilter.cpp
+ src/main/cpp/effect/CannyEdgeDetectionFilter.cpp
+ src/main/cpp/effect/BilateralFilter.cpp
+ src/main/cpp/effect/ColorMatrixFilter.cpp
+ src/main/cpp/effect/HSBFilter.cpp
+ src/main/cpp/effect/BeautifyFilter.cpp
+ src/main/cpp/effect/SobelEdgeDetectionFilter.cpp
+ src/main/cpp/effect/SketchFilter.cpp
+ src/main/cpp/effect/ToonFilter.cpp
+ src/main/cpp/effect/PixellationFilter.cpp
+ src/main/cpp/effect/SaturationFilter.cpp
+ src/main/cpp/effect/ContrastFilter.cpp
+ src/main/cpp/effect/ExposureFilter.cpp
+ src/main/cpp/effect/RGBFilter.cpp
+ src/main/cpp/effect/HueFilter.cpp
+ src/main/cpp/effect/WhiteBalanceFilter.cpp
+ src/main/cpp/effect/SmoothToonFilter.cpp
+ src/main/cpp/effect/PosterizeFilter.cpp
+ src/main/cpp/effect/LuminanceRangeFilter.cpp
+ src/main/cpp/effect/IOSBlurFilter.cpp
+ src/main/cpp/effect/NonMaximumSuppressionFilter.cpp
+ src/main/cpp/effect/SingleComponentGaussianBlurMonoFilter.cpp
+ src/main/cpp/effect/SingleComponentGaussianBlurFilter.cpp
+ src/main/cpp/effect/Convolution3x3Filter.cpp
+ src/main/cpp/effect/EmbossFilter.cpp
+ src/main/cpp/effect/HalftoneFilter.cpp
+ src/main/cpp/effect/CrosshatchFilter.cpp
+ src/main/cpp/effect/SphereRefractionFilter.cpp
+ src/main/cpp/effect/GlassSphereFilter.cpp
+ )
+
+#add_library( # Sets the name of the library.
+# native-lib
+#
+# # Sets the library as a shared library.
+# SHARED
+#
+# # Provides a relative path to your source file(s).
+# rc/main/cpp/native-lib.cpp)
+#
+#add_library( # Sets the name of the library.
+# triangle-lib
+#
+# # Sets the library as a shared library.
+# SHARED
+#
+# # Provides a relative path to your source file(s).
+# src/main/cpp/triangle.cpp)
+
+
+
+# Searches for a specified prebuilt library and stores the path as a
+# variable. Because CMake includes system libraries in the search path by
+# default, you only need to specify the name of the public NDK library
+# you want to add. CMake verifies that the library exists before
+# completing its build.
+
+find_library( # Sets the name of the path variable.
+ log-lib
+
+ # Specifies the name of the NDK library that
+ # you want CMake to locate.
+ log )
+
+# Specifies libraries CMake should link to your target library. You
+# can link multiple libraries, such as libraries you define in this
+# build script, prebuilt third-party libraries, or system libraries.
+
+#target_link_libraries( # Specifies the target library.
+# native-lib
+#
+# # Links the target library to the log library
+# # included in the NDK.
+# ${log-lib} )
+#
+#target_link_libraries( # Specifies the target library.
+# triangle-lib
+# android
+# GLESv3
+#
+# # Links the target library to the log library
+# # included in the NDK.
+# ${log-lib} )
+
+target_link_libraries( # Specifies the target library.
+ magicjni
+ android
+ GLESv3
+ EGL
+ jnigraphics
+
+ # Links the target library to the log library
+ # included in the NDK.
+ ${log-lib} )
+
+target_link_libraries(
+ GPUImage-x
+ ${log-lib}
+ GLESv2
+ jnigraphics )
+
+include(CheckCXXCompilerFlag)
+CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
+CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
+if(COMPILER_SUPPORTS_CXX11)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+elseif(COMPILER_SUPPORTS_CXX0X)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
+else()
+ message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
+endif()
+
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -frtti")
\ No newline at end of file
diff --git a/filter/build.gradle b/filter/build.gradle
new file mode 100644
index 0000000..b04eaf6
--- /dev/null
+++ b/filter/build.gradle
@@ -0,0 +1,59 @@
+apply plugin: 'com.android.library'
+
+apply plugin: 'kotlin-kapt'
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-android-extensions'
+
+
+android {
+ compileSdkVersion 28
+ defaultConfig {
+ minSdkVersion 21
+ targetSdkVersion 28
+ versionCode 1
+ versionName "1.0"
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+ externalNativeBuild {
+ cmake {
+ cppFlags "-std=c++11 -fexceptions"
+ }
+ }
+ ndk {
+ abiFilters "arm64-v8a"
+ }
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+ sourceSets.main {
+ jni.srcDirs = []
+ jniLibs.srcDirs = ['libs']
+ }
+
+ externalNativeBuild {
+ cmake {
+ path "CMakeLists.txt"
+ }
+ }
+ compileOptions {
+ targetCompatibility 1.8
+ sourceCompatibility 1.8
+ }
+
+ publishNonDefault true
+}
+
+dependencies {
+ implementation fileTree(include: ['*.jar'], dir: 'libs')
+ api 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.21'
+}
+
+kapt {
+ arguments {
+ arg("AROUTER_MODULE_NAME", project.getName())
+ }
+}
+
diff --git a/filter/proguard-rules.pro b/filter/proguard-rules.pro
new file mode 100644
index 0000000..f1b4245
--- /dev/null
+++ b/filter/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/filter/src/main/AndroidManifest.xml b/filter/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..9cc24db
--- /dev/null
+++ b/filter/src/main/AndroidManifest.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/assets/amaro.glsl b/filter/src/main/assets/amaro.glsl
similarity index 100%
rename from app/src/main/assets/amaro.glsl
rename to filter/src/main/assets/amaro.glsl
diff --git a/app/src/main/assets/antique.glsl b/filter/src/main/assets/antique.glsl
similarity index 100%
rename from app/src/main/assets/antique.glsl
rename to filter/src/main/assets/antique.glsl
diff --git a/app/src/main/assets/blackcat.glsl b/filter/src/main/assets/blackcat.glsl
similarity index 100%
rename from app/src/main/assets/blackcat.glsl
rename to filter/src/main/assets/blackcat.glsl
diff --git a/app/src/main/assets/brannan.glsl b/filter/src/main/assets/brannan.glsl
similarity index 100%
rename from app/src/main/assets/brannan.glsl
rename to filter/src/main/assets/brannan.glsl
diff --git a/app/src/main/assets/brooklyn.glsl b/filter/src/main/assets/brooklyn.glsl
similarity index 100%
rename from app/src/main/assets/brooklyn.glsl
rename to filter/src/main/assets/brooklyn.glsl
diff --git a/app/src/main/assets/calm.glsl b/filter/src/main/assets/calm.glsl
similarity index 100%
rename from app/src/main/assets/calm.glsl
rename to filter/src/main/assets/calm.glsl
diff --git a/app/src/main/assets/camera.frag b/filter/src/main/assets/camera.frag
similarity index 100%
rename from app/src/main/assets/camera.frag
rename to filter/src/main/assets/camera.frag
diff --git a/app/src/main/assets/camera.vert b/filter/src/main/assets/camera.vert
similarity index 100%
rename from app/src/main/assets/camera.vert
rename to filter/src/main/assets/camera.vert
diff --git a/app/src/main/assets/common_f.glsl b/filter/src/main/assets/common_f.glsl
similarity index 100%
rename from app/src/main/assets/common_f.glsl
rename to filter/src/main/assets/common_f.glsl
diff --git a/app/src/main/assets/cool.glsl b/filter/src/main/assets/cool.glsl
similarity index 100%
rename from app/src/main/assets/cool.glsl
rename to filter/src/main/assets/cool.glsl
diff --git a/app/src/main/assets/crayon.glsl b/filter/src/main/assets/crayon.glsl
similarity index 100%
rename from app/src/main/assets/crayon.glsl
rename to filter/src/main/assets/crayon.glsl
diff --git a/app/src/main/assets/default_fragment.glsl b/filter/src/main/assets/default_fragment.glsl
similarity index 100%
rename from app/src/main/assets/default_fragment.glsl
rename to filter/src/main/assets/default_fragment.glsl
diff --git a/app/src/main/assets/default_none_fragment.glsl b/filter/src/main/assets/default_none_fragment.glsl
similarity index 100%
rename from app/src/main/assets/default_none_fragment.glsl
rename to filter/src/main/assets/default_none_fragment.glsl
diff --git a/app/src/main/assets/default_vertex.glsl b/filter/src/main/assets/default_vertex.glsl
similarity index 100%
rename from app/src/main/assets/default_vertex.glsl
rename to filter/src/main/assets/default_vertex.glsl
diff --git a/app/src/main/assets/earlybird.glsl b/filter/src/main/assets/earlybird.glsl
similarity index 100%
rename from app/src/main/assets/earlybird.glsl
rename to filter/src/main/assets/earlybird.glsl
diff --git a/app/src/main/assets/emerald.glsl b/filter/src/main/assets/emerald.glsl
similarity index 100%
rename from app/src/main/assets/emerald.glsl
rename to filter/src/main/assets/emerald.glsl
diff --git a/app/src/main/assets/evergreen.glsl b/filter/src/main/assets/evergreen.glsl
similarity index 100%
rename from app/src/main/assets/evergreen.glsl
rename to filter/src/main/assets/evergreen.glsl
diff --git a/app/src/main/assets/filter/amaro_mask1.jpg b/filter/src/main/assets/filter/amaro_mask1.jpg
similarity index 100%
rename from app/src/main/assets/filter/amaro_mask1.jpg
rename to filter/src/main/assets/filter/amaro_mask1.jpg
diff --git a/app/src/main/assets/filter/amaro_mask2.jpg b/filter/src/main/assets/filter/amaro_mask2.jpg
similarity index 100%
rename from app/src/main/assets/filter/amaro_mask2.jpg
rename to filter/src/main/assets/filter/amaro_mask2.jpg
diff --git a/app/src/main/assets/filter/amaromap.png b/filter/src/main/assets/filter/amaromap.png
similarity index 100%
rename from app/src/main/assets/filter/amaromap.png
rename to filter/src/main/assets/filter/amaromap.png
diff --git a/app/src/main/assets/filter/blackboard1024.png b/filter/src/main/assets/filter/blackboard1024.png
similarity index 100%
rename from app/src/main/assets/filter/blackboard1024.png
rename to filter/src/main/assets/filter/blackboard1024.png
diff --git a/app/src/main/assets/filter/blend1.jpg b/filter/src/main/assets/filter/blend1.jpg
similarity index 100%
rename from app/src/main/assets/filter/blend1.jpg
rename to filter/src/main/assets/filter/blend1.jpg
diff --git a/app/src/main/assets/filter/bluevintage_mask1.jpg b/filter/src/main/assets/filter/bluevintage_mask1.jpg
similarity index 100%
rename from app/src/main/assets/filter/bluevintage_mask1.jpg
rename to filter/src/main/assets/filter/bluevintage_mask1.jpg
diff --git a/app/src/main/assets/filter/brannan_blowout.png b/filter/src/main/assets/filter/brannan_blowout.png
similarity index 100%
rename from app/src/main/assets/filter/brannan_blowout.png
rename to filter/src/main/assets/filter/brannan_blowout.png
diff --git a/app/src/main/assets/filter/brannan_contrast.png b/filter/src/main/assets/filter/brannan_contrast.png
similarity index 100%
rename from app/src/main/assets/filter/brannan_contrast.png
rename to filter/src/main/assets/filter/brannan_contrast.png
diff --git a/app/src/main/assets/filter/brannan_luma.png b/filter/src/main/assets/filter/brannan_luma.png
similarity index 100%
rename from app/src/main/assets/filter/brannan_luma.png
rename to filter/src/main/assets/filter/brannan_luma.png
diff --git a/app/src/main/assets/filter/brannan_process.png b/filter/src/main/assets/filter/brannan_process.png
similarity index 100%
rename from app/src/main/assets/filter/brannan_process.png
rename to filter/src/main/assets/filter/brannan_process.png
diff --git a/app/src/main/assets/filter/brannan_screen.png b/filter/src/main/assets/filter/brannan_screen.png
similarity index 100%
rename from app/src/main/assets/filter/brannan_screen.png
rename to filter/src/main/assets/filter/brannan_screen.png
diff --git a/app/src/main/assets/filter/brooklynCurves1.png b/filter/src/main/assets/filter/brooklynCurves1.png
similarity index 100%
rename from app/src/main/assets/filter/brooklynCurves1.png
rename to filter/src/main/assets/filter/brooklynCurves1.png
diff --git a/app/src/main/assets/filter/brooklynCurves2.png b/filter/src/main/assets/filter/brooklynCurves2.png
similarity index 100%
rename from app/src/main/assets/filter/brooklynCurves2.png
rename to filter/src/main/assets/filter/brooklynCurves2.png
diff --git a/app/src/main/assets/filter/calm_mask1.jpg b/filter/src/main/assets/filter/calm_mask1.jpg
similarity index 100%
rename from app/src/main/assets/filter/calm_mask1.jpg
rename to filter/src/main/assets/filter/calm_mask1.jpg
diff --git a/app/src/main/assets/filter/calm_mask2.jpg b/filter/src/main/assets/filter/calm_mask2.jpg
similarity index 100%
rename from app/src/main/assets/filter/calm_mask2.jpg
rename to filter/src/main/assets/filter/calm_mask2.jpg
diff --git a/app/src/main/assets/filter/earlybirdOverlayMap.png b/filter/src/main/assets/filter/earlybirdOverlayMap.png
similarity index 100%
rename from app/src/main/assets/filter/earlybirdOverlayMap.png
rename to filter/src/main/assets/filter/earlybirdOverlayMap.png
diff --git a/app/src/main/assets/filter/earlybirdblowout.png b/filter/src/main/assets/filter/earlybirdblowout.png
similarity index 100%
rename from app/src/main/assets/filter/earlybirdblowout.png
rename to filter/src/main/assets/filter/earlybirdblowout.png
diff --git a/app/src/main/assets/filter/earlybirdcurves.png b/filter/src/main/assets/filter/earlybirdcurves.png
similarity index 100%
rename from app/src/main/assets/filter/earlybirdcurves.png
rename to filter/src/main/assets/filter/earlybirdcurves.png
diff --git a/app/src/main/assets/filter/earlybirdmap.png b/filter/src/main/assets/filter/earlybirdmap.png
similarity index 100%
rename from app/src/main/assets/filter/earlybirdmap.png
rename to filter/src/main/assets/filter/earlybirdmap.png
diff --git a/app/src/main/assets/filter/earlybirdoverlaymap_new.png b/filter/src/main/assets/filter/earlybirdoverlaymap_new.png
similarity index 100%
rename from app/src/main/assets/filter/earlybirdoverlaymap_new.png
rename to filter/src/main/assets/filter/earlybirdoverlaymap_new.png
diff --git a/app/src/main/assets/filter/edgeburn.png b/filter/src/main/assets/filter/edgeburn.png
similarity index 100%
rename from app/src/main/assets/filter/edgeburn.png
rename to filter/src/main/assets/filter/edgeburn.png
diff --git a/app/src/main/assets/filter/fairy_tale.png b/filter/src/main/assets/filter/fairy_tale.png
similarity index 100%
rename from app/src/main/assets/filter/fairy_tale.png
rename to filter/src/main/assets/filter/fairy_tale.png
diff --git a/app/src/main/assets/filter/filter_map_first.png b/filter/src/main/assets/filter/filter_map_first.png
similarity index 100%
rename from app/src/main/assets/filter/filter_map_first.png
rename to filter/src/main/assets/filter/filter_map_first.png
diff --git a/app/src/main/assets/filter/flower_layer2c.jpg b/filter/src/main/assets/filter/flower_layer2c.jpg
similarity index 100%
rename from app/src/main/assets/filter/flower_layer2c.jpg
rename to filter/src/main/assets/filter/flower_layer2c.jpg
diff --git a/app/src/main/assets/filter/freud_rand.png b/filter/src/main/assets/filter/freud_rand.png
similarity index 100%
rename from app/src/main/assets/filter/freud_rand.png
rename to filter/src/main/assets/filter/freud_rand.png
diff --git a/app/src/main/assets/filter/healthy_mask_1.jpg b/filter/src/main/assets/filter/healthy_mask_1.jpg
similarity index 100%
rename from app/src/main/assets/filter/healthy_mask_1.jpg
rename to filter/src/main/assets/filter/healthy_mask_1.jpg
diff --git a/app/src/main/assets/filter/hefegradientmap.png b/filter/src/main/assets/filter/hefegradientmap.png
similarity index 100%
rename from app/src/main/assets/filter/hefegradientmap.png
rename to filter/src/main/assets/filter/hefegradientmap.png
diff --git a/app/src/main/assets/filter/hefemap.png b/filter/src/main/assets/filter/hefemap.png
similarity index 100%
rename from app/src/main/assets/filter/hefemap.png
rename to filter/src/main/assets/filter/hefemap.png
diff --git a/app/src/main/assets/filter/hefemetal.png b/filter/src/main/assets/filter/hefemetal.png
similarity index 100%
rename from app/src/main/assets/filter/hefemetal.png
rename to filter/src/main/assets/filter/hefemetal.png
diff --git a/app/src/main/assets/filter/hefesoftlight.png b/filter/src/main/assets/filter/hefesoftlight.png
similarity index 100%
rename from app/src/main/assets/filter/hefesoftlight.png
rename to filter/src/main/assets/filter/hefesoftlight.png
diff --git a/app/src/main/assets/filter/hudsonbackground.png b/filter/src/main/assets/filter/hudsonbackground.png
similarity index 100%
rename from app/src/main/assets/filter/hudsonbackground.png
rename to filter/src/main/assets/filter/hudsonbackground.png
diff --git a/app/src/main/assets/filter/hudsonmap.png b/filter/src/main/assets/filter/hudsonmap.png
similarity index 100%
rename from app/src/main/assets/filter/hudsonmap.png
rename to filter/src/main/assets/filter/hudsonmap.png
diff --git a/app/src/main/assets/filter/inkwellmap.png b/filter/src/main/assets/filter/inkwellmap.png
similarity index 100%
rename from app/src/main/assets/filter/inkwellmap.png
rename to filter/src/main/assets/filter/inkwellmap.png
diff --git a/app/src/main/assets/filter/kelvinmap.png b/filter/src/main/assets/filter/kelvinmap.png
similarity index 100%
rename from app/src/main/assets/filter/kelvinmap.png
rename to filter/src/main/assets/filter/kelvinmap.png
diff --git a/app/src/main/assets/filter/line_layer_c.jpg b/filter/src/main/assets/filter/line_layer_c.jpg
similarity index 100%
rename from app/src/main/assets/filter/line_layer_c.jpg
rename to filter/src/main/assets/filter/line_layer_c.jpg
diff --git a/app/src/main/assets/filter/lomomap_new.png b/filter/src/main/assets/filter/lomomap_new.png
similarity index 100%
rename from app/src/main/assets/filter/lomomap_new.png
rename to filter/src/main/assets/filter/lomomap_new.png
diff --git a/app/src/main/assets/filter/lookup_amatorka_02.png b/filter/src/main/assets/filter/lookup_amatorka_02.png
similarity index 100%
rename from app/src/main/assets/filter/lookup_amatorka_02.png
rename to filter/src/main/assets/filter/lookup_amatorka_02.png
diff --git a/app/src/main/assets/filter/lookup_highkey.png b/filter/src/main/assets/filter/lookup_highkey.png
similarity index 100%
rename from app/src/main/assets/filter/lookup_highkey.png
rename to filter/src/main/assets/filter/lookup_highkey.png
diff --git a/app/src/main/assets/filter/lookup_vertigo.png b/filter/src/main/assets/filter/lookup_vertigo.png
similarity index 100%
rename from app/src/main/assets/filter/lookup_vertigo.png
rename to filter/src/main/assets/filter/lookup_vertigo.png
diff --git a/app/src/main/assets/filter/n1977blowout.png b/filter/src/main/assets/filter/n1977blowout.png
similarity index 100%
rename from app/src/main/assets/filter/n1977blowout.png
rename to filter/src/main/assets/filter/n1977blowout.png
diff --git a/app/src/main/assets/filter/n1977map.png b/filter/src/main/assets/filter/n1977map.png
similarity index 100%
rename from app/src/main/assets/filter/n1977map.png
rename to filter/src/main/assets/filter/n1977map.png
diff --git a/app/src/main/assets/filter/nashvillemap.png b/filter/src/main/assets/filter/nashvillemap.png
similarity index 100%
rename from app/src/main/assets/filter/nashvillemap.png
rename to filter/src/main/assets/filter/nashvillemap.png
diff --git a/app/src/main/assets/filter/overlaymap.png b/filter/src/main/assets/filter/overlaymap.png
similarity index 100%
rename from app/src/main/assets/filter/overlaymap.png
rename to filter/src/main/assets/filter/overlaymap.png
diff --git a/app/src/main/assets/filter/pixar_curves.png b/filter/src/main/assets/filter/pixar_curves.png
similarity index 100%
rename from app/src/main/assets/filter/pixar_curves.png
rename to filter/src/main/assets/filter/pixar_curves.png
diff --git a/app/src/main/assets/filter/rise_mask1.jpg b/filter/src/main/assets/filter/rise_mask1.jpg
similarity index 100%
rename from app/src/main/assets/filter/rise_mask1.jpg
rename to filter/src/main/assets/filter/rise_mask1.jpg
diff --git a/app/src/main/assets/filter/rise_mask2.jpg b/filter/src/main/assets/filter/rise_mask2.jpg
similarity index 100%
rename from app/src/main/assets/filter/rise_mask2.jpg
rename to filter/src/main/assets/filter/rise_mask2.jpg
diff --git a/app/src/main/assets/filter/risemap.png b/filter/src/main/assets/filter/risemap.png
similarity index 100%
rename from app/src/main/assets/filter/risemap.png
rename to filter/src/main/assets/filter/risemap.png
diff --git a/app/src/main/assets/filter/sierramap.png b/filter/src/main/assets/filter/sierramap.png
similarity index 100%
rename from app/src/main/assets/filter/sierramap.png
rename to filter/src/main/assets/filter/sierramap.png
diff --git a/app/src/main/assets/filter/sierravignette.png b/filter/src/main/assets/filter/sierravignette.png
similarity index 100%
rename from app/src/main/assets/filter/sierravignette.png
rename to filter/src/main/assets/filter/sierravignette.png
diff --git a/app/src/main/assets/filter/softlight.png b/filter/src/main/assets/filter/softlight.png
similarity index 100%
rename from app/src/main/assets/filter/softlight.png
rename to filter/src/main/assets/filter/softlight.png
diff --git a/app/src/main/assets/filter/sutrocurves.png b/filter/src/main/assets/filter/sutrocurves.png
similarity index 100%
rename from app/src/main/assets/filter/sutrocurves.png
rename to filter/src/main/assets/filter/sutrocurves.png
diff --git a/app/src/main/assets/filter/sutroedgeburn.png b/filter/src/main/assets/filter/sutroedgeburn.png
similarity index 100%
rename from app/src/main/assets/filter/sutroedgeburn.png
rename to filter/src/main/assets/filter/sutroedgeburn.png
diff --git a/app/src/main/assets/filter/sutrometal.png b/filter/src/main/assets/filter/sutrometal.png
similarity index 100%
rename from app/src/main/assets/filter/sutrometal.png
rename to filter/src/main/assets/filter/sutrometal.png
diff --git a/app/src/main/assets/filter/toastercolorshift.png b/filter/src/main/assets/filter/toastercolorshift.png
similarity index 100%
rename from app/src/main/assets/filter/toastercolorshift.png
rename to filter/src/main/assets/filter/toastercolorshift.png
diff --git a/app/src/main/assets/filter/toastercurves.png b/filter/src/main/assets/filter/toastercurves.png
similarity index 100%
rename from app/src/main/assets/filter/toastercurves.png
rename to filter/src/main/assets/filter/toastercurves.png
diff --git a/app/src/main/assets/filter/toastermetal.png b/filter/src/main/assets/filter/toastermetal.png
similarity index 100%
rename from app/src/main/assets/filter/toastermetal.png
rename to filter/src/main/assets/filter/toastermetal.png
diff --git a/app/src/main/assets/filter/toasteroverlaymapwarm.png b/filter/src/main/assets/filter/toasteroverlaymapwarm.png
similarity index 100%
rename from app/src/main/assets/filter/toasteroverlaymapwarm.png
rename to filter/src/main/assets/filter/toasteroverlaymapwarm.png
diff --git a/app/src/main/assets/filter/toastersoftlight.png b/filter/src/main/assets/filter/toastersoftlight.png
similarity index 100%
rename from app/src/main/assets/filter/toastersoftlight.png
rename to filter/src/main/assets/filter/toastersoftlight.png
diff --git a/app/src/main/assets/filter/toy_mask1.jpg b/filter/src/main/assets/filter/toy_mask1.jpg
similarity index 100%
rename from app/src/main/assets/filter/toy_mask1.jpg
rename to filter/src/main/assets/filter/toy_mask1.jpg
diff --git a/app/src/main/assets/filter/toy_mask2.jpg b/filter/src/main/assets/filter/toy_mask2.jpg
similarity index 100%
rename from app/src/main/assets/filter/toy_mask2.jpg
rename to filter/src/main/assets/filter/toy_mask2.jpg
diff --git a/app/src/main/assets/filter/toy_mask3.jpg b/filter/src/main/assets/filter/toy_mask3.jpg
similarity index 100%
rename from app/src/main/assets/filter/toy_mask3.jpg
rename to filter/src/main/assets/filter/toy_mask3.jpg
diff --git a/app/src/main/assets/filter/valenciagradientmap.png b/filter/src/main/assets/filter/valenciagradientmap.png
similarity index 100%
rename from app/src/main/assets/filter/valenciagradientmap.png
rename to filter/src/main/assets/filter/valenciagradientmap.png
diff --git a/app/src/main/assets/filter/valenciamap.png b/filter/src/main/assets/filter/valenciamap.png
similarity index 100%
rename from app/src/main/assets/filter/valenciamap.png
rename to filter/src/main/assets/filter/valenciamap.png
diff --git a/app/src/main/assets/filter/vignette_map.png b/filter/src/main/assets/filter/vignette_map.png
similarity index 100%
rename from app/src/main/assets/filter/vignette_map.png
rename to filter/src/main/assets/filter/vignette_map.png
diff --git a/app/src/main/assets/filter/vignettemap_new.png b/filter/src/main/assets/filter/vignettemap_new.png
similarity index 100%
rename from app/src/main/assets/filter/vignettemap_new.png
rename to filter/src/main/assets/filter/vignettemap_new.png
diff --git a/app/src/main/assets/filter/walden_map.png b/filter/src/main/assets/filter/walden_map.png
similarity index 100%
rename from app/src/main/assets/filter/walden_map.png
rename to filter/src/main/assets/filter/walden_map.png
diff --git a/app/src/main/assets/filter/warm_layer1.jpg b/filter/src/main/assets/filter/warm_layer1.jpg
similarity index 100%
rename from app/src/main/assets/filter/warm_layer1.jpg
rename to filter/src/main/assets/filter/warm_layer1.jpg
diff --git a/app/src/main/assets/filter/xpromap.png b/filter/src/main/assets/filter/xpromap.png
similarity index 100%
rename from app/src/main/assets/filter/xpromap.png
rename to filter/src/main/assets/filter/xpromap.png
diff --git a/app/src/main/assets/freud.glsl b/filter/src/main/assets/freud.glsl
similarity index 100%
rename from app/src/main/assets/freud.glsl
rename to filter/src/main/assets/freud.glsl
diff --git a/app/src/main/assets/glitch_f.glsl b/filter/src/main/assets/glitch_f.glsl
similarity index 86%
rename from app/src/main/assets/glitch_f.glsl
rename to filter/src/main/assets/glitch_f.glsl
index f5e6661..14ff355 100644
--- a/app/src/main/assets/glitch_f.glsl
+++ b/filter/src/main/assets/glitch_f.glsl
@@ -10,8 +10,8 @@ precision highp float;
out vec4 glFragColor;
float nrand(in float x,in float y){
- //fract(x) = x - floor(x);
- //dot是向量点乘,sin就是正弦函数
+ //fract(x) = x - floor(x); 返回x的小数部分
+ //dot是向量点乘,,sin就是正弦函数
return fract(sin(dot(vec2(x,y) ,vec2(12.9898,78.233))) * 43758.5453);
}
@@ -23,7 +23,7 @@ precision highp float;
float jitter = nrand(v ,0.0) * 2.0 - 1.0;
float drift = uColorDrift;
//计算向左或向右偏移
- //step是gl自带函数,意思是,如果第一个参数大于第二个参数,那么返回0,否则返回1
+ //step意思是,如果第一个参数大于第二个参数,那么返回0,否则返回1
float offsetParam = step(uScanLineJitter.y,abs(jitter));
//如果offset为0就不偏移,如果为1,就偏移jtter*uScanLineJitter.x的位置
jitter = jitter * offsetParam * uScanLineJitter.x;
diff --git a/app/src/main/assets/healthy.glsl b/filter/src/main/assets/healthy.glsl
similarity index 100%
rename from app/src/main/assets/healthy.glsl
rename to filter/src/main/assets/healthy.glsl
diff --git a/app/src/main/assets/hefe.glsl b/filter/src/main/assets/hefe.glsl
similarity index 100%
rename from app/src/main/assets/hefe.glsl
rename to filter/src/main/assets/hefe.glsl
diff --git a/app/src/main/assets/hudson.glsl b/filter/src/main/assets/hudson.glsl
similarity index 100%
rename from app/src/main/assets/hudson.glsl
rename to filter/src/main/assets/hudson.glsl
diff --git a/app/src/main/assets/inkwell.glsl b/filter/src/main/assets/inkwell.glsl
similarity index 100%
rename from app/src/main/assets/inkwell.glsl
rename to filter/src/main/assets/inkwell.glsl
diff --git a/app/src/main/assets/kevin_new.glsl b/filter/src/main/assets/kevin_new.glsl
similarity index 100%
rename from app/src/main/assets/kevin_new.glsl
rename to filter/src/main/assets/kevin_new.glsl
diff --git a/app/src/main/assets/latte.glsl b/filter/src/main/assets/latte.glsl
similarity index 100%
rename from app/src/main/assets/latte.glsl
rename to filter/src/main/assets/latte.glsl
diff --git a/app/src/main/assets/lomo.glsl b/filter/src/main/assets/lomo.glsl
similarity index 100%
rename from app/src/main/assets/lomo.glsl
rename to filter/src/main/assets/lomo.glsl
diff --git a/app/src/main/assets/lookup.glsl b/filter/src/main/assets/lookup.glsl
similarity index 100%
rename from app/src/main/assets/lookup.glsl
rename to filter/src/main/assets/lookup.glsl
diff --git a/app/src/main/assets/n1977.glsl b/filter/src/main/assets/n1977.glsl
similarity index 100%
rename from app/src/main/assets/n1977.glsl
rename to filter/src/main/assets/n1977.glsl
diff --git a/app/src/main/assets/nashville.glsl b/filter/src/main/assets/nashville.glsl
similarity index 100%
rename from app/src/main/assets/nashville.glsl
rename to filter/src/main/assets/nashville.glsl
diff --git a/app/src/main/assets/nofilter_f.glsl b/filter/src/main/assets/nofilter_f.glsl
similarity index 100%
rename from app/src/main/assets/nofilter_f.glsl
rename to filter/src/main/assets/nofilter_f.glsl
diff --git a/app/src/main/assets/nofilter_v.glsl b/filter/src/main/assets/nofilter_v.glsl
similarity index 100%
rename from app/src/main/assets/nofilter_v.glsl
rename to filter/src/main/assets/nofilter_v.glsl
diff --git a/app/src/main/assets/none.glsl b/filter/src/main/assets/none.glsl
similarity index 100%
rename from app/src/main/assets/none.glsl
rename to filter/src/main/assets/none.glsl
diff --git a/app/src/main/assets/nostalgia.glsl b/filter/src/main/assets/nostalgia.glsl
similarity index 100%
rename from app/src/main/assets/nostalgia.glsl
rename to filter/src/main/assets/nostalgia.glsl
diff --git a/app/src/main/assets/pixar.glsl b/filter/src/main/assets/pixar.glsl
similarity index 100%
rename from app/src/main/assets/pixar.glsl
rename to filter/src/main/assets/pixar.glsl
diff --git a/app/src/main/assets/rise.glsl b/filter/src/main/assets/rise.glsl
similarity index 100%
rename from app/src/main/assets/rise.glsl
rename to filter/src/main/assets/rise.glsl
diff --git a/app/src/main/assets/romance.glsl b/filter/src/main/assets/romance.glsl
similarity index 100%
rename from app/src/main/assets/romance.glsl
rename to filter/src/main/assets/romance.glsl
diff --git a/app/src/main/assets/sakura.glsl b/filter/src/main/assets/sakura.glsl
similarity index 100%
rename from app/src/main/assets/sakura.glsl
rename to filter/src/main/assets/sakura.glsl
diff --git a/filter/src/main/assets/shakeeffect_f.glsl b/filter/src/main/assets/shakeeffect_f.glsl
new file mode 100644
index 0000000..20a195e
--- /dev/null
+++ b/filter/src/main/assets/shakeeffect_f.glsl
@@ -0,0 +1,21 @@
+#version 300 es
+precision mediump float;
+ //每个点的xy坐标
+ in vec2 textureCoordinate;
+ //对应纹理
+ uniform sampler2D inputImageTexture;
+ uniform float uTextureCoordOffset;
+ out vec4 glFragColor;
+
+ void main()
+ {
+ //直接采样蓝色色值
+ vec4 blue = texture(inputImageTexture,textureCoordinate);
+ //从效果看,绿色和红色色值特别明显,所以需要对其色值偏移。绿色和红色需要分开方向,不然重叠一起会混色。
+ //坐标向左上偏移,然后再采样色值
+ vec4 green = texture(inputImageTexture, vec2(textureCoordinate.x + uTextureCoordOffset, textureCoordinate.y + uTextureCoordOffset));
+ //坐标向右下偏移,然后再采样色值
+ vec4 red = texture(inputImageTexture,vec2(textureCoordinate.x - uTextureCoordOffset,textureCoordinate.y - uTextureCoordOffset));
+ //RG两个经过偏移后分别采样,B沿用原来的色值,透明度为1,组合最终输出
+ glFragColor = vec4(red.r,green.g,blue.b,blue.a);
+ }
\ No newline at end of file
diff --git a/app/src/main/assets/sierra.glsl b/filter/src/main/assets/sierra.glsl
similarity index 100%
rename from app/src/main/assets/sierra.glsl
rename to filter/src/main/assets/sierra.glsl
diff --git a/app/src/main/assets/sketch.glsl b/filter/src/main/assets/sketch.glsl
similarity index 100%
rename from app/src/main/assets/sketch.glsl
rename to filter/src/main/assets/sketch.glsl
diff --git a/app/src/main/assets/skinwhiten.glsl b/filter/src/main/assets/skinwhiten.glsl
similarity index 100%
rename from app/src/main/assets/skinwhiten.glsl
rename to filter/src/main/assets/skinwhiten.glsl
diff --git a/app/src/main/assets/soulout_f.glsl b/filter/src/main/assets/soulout_f.glsl
similarity index 100%
rename from app/src/main/assets/soulout_f.glsl
rename to filter/src/main/assets/soulout_f.glsl
diff --git a/app/src/main/assets/soulout_v.glsl b/filter/src/main/assets/soulout_v.glsl
similarity index 100%
rename from app/src/main/assets/soulout_v.glsl
rename to filter/src/main/assets/soulout_v.glsl
diff --git a/app/src/main/assets/suger_tablets.glsl b/filter/src/main/assets/suger_tablets.glsl
similarity index 100%
rename from app/src/main/assets/suger_tablets.glsl
rename to filter/src/main/assets/suger_tablets.glsl
diff --git a/app/src/main/assets/sunrise.glsl b/filter/src/main/assets/sunrise.glsl
similarity index 100%
rename from app/src/main/assets/sunrise.glsl
rename to filter/src/main/assets/sunrise.glsl
diff --git a/app/src/main/assets/sunset.glsl b/filter/src/main/assets/sunset.glsl
similarity index 100%
rename from app/src/main/assets/sunset.glsl
rename to filter/src/main/assets/sunset.glsl
diff --git a/app/src/main/assets/sutro.glsl b/filter/src/main/assets/sutro.glsl
similarity index 100%
rename from app/src/main/assets/sutro.glsl
rename to filter/src/main/assets/sutro.glsl
diff --git a/app/src/main/assets/sweets.glsl b/filter/src/main/assets/sweets.glsl
similarity index 100%
rename from app/src/main/assets/sweets.glsl
rename to filter/src/main/assets/sweets.glsl
diff --git a/app/src/main/assets/tender.glsl b/filter/src/main/assets/tender.glsl
similarity index 100%
rename from app/src/main/assets/tender.glsl
rename to filter/src/main/assets/tender.glsl
diff --git a/filter/src/main/assets/three_win.glsl b/filter/src/main/assets/three_win.glsl
new file mode 100644
index 0000000..1385436
--- /dev/null
+++ b/filter/src/main/assets/three_win.glsl
@@ -0,0 +1,20 @@
+#version 300 es
+precision mediump float;
+
+ in vec2 textureCoordinate;
+ uniform sampler2D inputImageTexture;
+ out vec4 glFragColor;
+
+ void main()
+ {
+ highp float y;
+ if(textureCoordinate.y>=0.0 &&textureCoordinate.y<=0.33){
+ y = textureCoordinate.y + 0.33;
+ glFragColor = texture(inputImageTexture,vec2(textureCoordinate.x,y));
+ }else if(textureCoordinate.y>0.33 &&textureCoordinate.y<=0.66){
+ glFragColor = texture(inputImageTexture,textureCoordinate);
+ }else{
+ y = textureCoordinate.y - 0.33;
+ glFragColor = texture(inputImageTexture,vec2(textureCoordinate.x,y));
+ }
+ }
\ No newline at end of file
diff --git a/app/src/main/assets/toaster2_filter_shader.glsl b/filter/src/main/assets/toaster2_filter_shader.glsl
similarity index 100%
rename from app/src/main/assets/toaster2_filter_shader.glsl
rename to filter/src/main/assets/toaster2_filter_shader.glsl
diff --git a/app/src/main/assets/valencia.glsl b/filter/src/main/assets/valencia.glsl
similarity index 100%
rename from app/src/main/assets/valencia.glsl
rename to filter/src/main/assets/valencia.glsl
diff --git a/app/src/main/assets/verigo_f.glsl b/filter/src/main/assets/verigo_f.glsl
similarity index 100%
rename from app/src/main/assets/verigo_f.glsl
rename to filter/src/main/assets/verigo_f.glsl
diff --git a/app/src/main/assets/verigo_f2.glsl b/filter/src/main/assets/verigo_f2.glsl
similarity index 92%
rename from app/src/main/assets/verigo_f2.glsl
rename to filter/src/main/assets/verigo_f2.glsl
index cde79ac..cf81710 100644
--- a/app/src/main/assets/verigo_f2.glsl
+++ b/filter/src/main/assets/verigo_f2.glsl
@@ -7,6 +7,7 @@ uniform sampler2D lookupTable; // 颜色查找表纹理
out vec4 glFragColor;
+//固定的Lut纹理对换计算
vec4 getLutColor(vec4 textureColor,sampler2D lookupTexture){
float blueColor = textureColor.b * 63.0;
@@ -36,7 +37,10 @@ vec4 getLutColor(vec4 textureColor,sampler2D lookupTexture){
}
void main(){
+ //上一帧纹理
vec4 lastFrame = texture(inputTextureLast,textureCoordinate);
+ //此帧对应的Lut转换纹理
vec4 currentFrame = getLutColor(texture(inputImageTexture,textureCoordinate),lookupTable);
+ //上一帧和此帧混色处理
glFragColor = vec4(0.95 * lastFrame.r + 0.05* currentFrame.r,currentFrame.g * 0.2 + lastFrame.g * 0.8, currentFrame.b,1.0);
}
\ No newline at end of file
diff --git a/app/src/main/assets/walden.glsl b/filter/src/main/assets/walden.glsl
similarity index 100%
rename from app/src/main/assets/walden.glsl
rename to filter/src/main/assets/walden.glsl
diff --git a/app/src/main/assets/warm.glsl b/filter/src/main/assets/warm.glsl
similarity index 100%
rename from app/src/main/assets/warm.glsl
rename to filter/src/main/assets/warm.glsl
diff --git a/app/src/main/assets/whitecat.glsl b/filter/src/main/assets/whitecat.glsl
similarity index 100%
rename from app/src/main/assets/whitecat.glsl
rename to filter/src/main/assets/whitecat.glsl
diff --git a/app/src/main/assets/whiteshine_f.glsl b/filter/src/main/assets/whiteshine_f.glsl
similarity index 82%
rename from app/src/main/assets/whiteshine_f.glsl
rename to filter/src/main/assets/whiteshine_f.glsl
index 9821491..583a21d 100644
--- a/app/src/main/assets/whiteshine_f.glsl
+++ b/filter/src/main/assets/whiteshine_f.glsl
@@ -10,5 +10,6 @@ precision mediump float;
void main()
{
vec4 color = texture(inputImageTexture,textureCoordinate);
+ //最大值为1,色值全部变白,最小值回回到原本的色值
glFragColor = vec4(color.r + uAdditionalColor,color.g+uAdditionalColor,color.b+uAdditionalColor,color.a);
}
\ No newline at end of file
diff --git a/app/src/main/assets/xproii_filter_shader.glsl b/filter/src/main/assets/xproii_filter_shader.glsl
similarity index 100%
rename from app/src/main/assets/xproii_filter_shader.glsl
rename to filter/src/main/assets/xproii_filter_shader.glsl
diff --git a/filter/src/main/cpp/Common/Platform.h b/filter/src/main/cpp/Common/Platform.h
new file mode 100644
index 0000000..c07cff1
--- /dev/null
+++ b/filter/src/main/cpp/Common/Platform.h
@@ -0,0 +1,33 @@
+#ifndef OPENGLES_PLATFORM_H
+#define OPENGLES_PLATFORM_H
+
+#define LOG_TAG "GLES"
+#define IS_DEBUG TRUE
+
+#if __ANDROID__
+
+#include
+#include
+
+#if IS_DEBUG
+#define ESLog(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
+
+#else
+#define ESLog(...)
+
+#endif
+
+#elif __IOS__
+
+#import
+#import
+
+#if IS_DEBUG
+#define ESLog(fmt, ...) printf("%s: ",LOG_TAG);printf((fmt), ##__VA_ARGS__);printf("\n");
+
+#else
+#define ESLog(fmt, ...)
+
+#endif
+
+#endif
diff --git a/filter/src/main/cpp/GPUImagexJNI.cpp b/filter/src/main/cpp/GPUImagexJNI.cpp
new file mode 100755
index 0000000..4067438
--- /dev/null
+++ b/filter/src/main/cpp/GPUImagexJNI.cpp
@@ -0,0 +1,394 @@
+#if PLATFORM == PLATFORM_ANDROID
+
+#include
+#include
+#include
+#include "src/main/cpp/source/SourceImage.h"
+#include "src/main/cpp/source/SourceCamera.h"
+#include "src/main/cpp/source/TargetView.h"
+#include "src/main/cpp/effect/Filter.hpp"
+#include "src/main/cpp/source/Context.hpp"
+
+USING_NS_GI
+
+extern "C" {
+JNIEXPORT jlong JNICALL
+Java_com_cangwang_gpuimage_GPUImage_nativeSourceImageNew(
+ JNIEnv *env,
+ jclass obj)
+{
+ return (uintptr_t)(new SourceImage());
+};
+
+JNIEXPORT void JNICALL
+Java_com_cangwang_gpuimage_GPUImage_nativeSourceImageDestroy(
+ JNIEnv *env,
+ jclass obj,
+ jlong classId)
+{
+ ((SourceImage*)classId)->release();
+};
+
+JNIEXPORT void JNICALL
+Java_com_cangwang_gpuimage_GPUImage_nativeSourceImageFinalize(
+ JNIEnv *env,
+ jclass obj,
+ jlong classId)
+{
+ ((SourceImage*)classId)->releaseFramebuffer(false);
+ ((SourceImage*)classId)->release();
+};
+
+JNIEXPORT void JNICALL
+Java_com_cangwang_gpuimage_GPUImage_nativeSourceImageSetImage(
+ JNIEnv *env,
+ jclass obj,
+ jlong classId,
+ jobject bitmap)
+{
+ char* pData = 0;
+ AndroidBitmapInfo info;
+ void* pixels;
+ if ((AndroidBitmap_getInfo(env, bitmap, &info)) < 0){
+ //ERROR
+ return;
+ }
+
+ if ((AndroidBitmap_lockPixels(env, bitmap, &pixels)) >= 0){
+ ((SourceImage*)classId)->setImage(info.width, info.height, pixels);
+ }
+
+ AndroidBitmap_unlockPixels(env, bitmap);
+};
+
+JNIEXPORT jlong JNICALL
+Java_com_cangwang_gpuimage_GPUImage_nativeSourceCameraNew(
+ JNIEnv *env,
+ jclass obj)
+{
+ return (uintptr_t)(new SourceCamera());
+};
+
+JNIEXPORT void JNICALL
+Java_com_cangwang_gpuimage_GPUImage_nativeSourceCameraDestroy(
+ JNIEnv *env,
+ jclass obj,
+ jlong classId)
+{
+ ((SourceCamera*)classId)->release();
+};
+
+JNIEXPORT void JNICALL
+Java_com_cangwang_gpuimage_GPUImage_nativeSourceCameraFinalize(
+ JNIEnv *env,
+ jclass obj,
+ jlong classId)
+{
+ ((SourceCamera*)classId)->releaseFramebuffer(false);
+ ((SourceCamera*)classId)->release();
+};
+
+JNIEXPORT void JNICALL
+Java_com_cangwang_gpuimage_GPUImage_nativeSourceCameraSetFrame(
+ JNIEnv *env,
+ jclass obj,
+ jlong classId,
+ jint width,
+ jint height,
+ jintArray jdata,
+ jint rotation)
+{
+ jint* data = (jint*) (env->GetPrimitiveArrayCritical(jdata, 0));
+ ((SourceCamera*)classId)->setFrameData(width, height, data, (RotationMode)rotation);
+ env->ReleasePrimitiveArrayCritical(jdata, data, 0);
+};
+
+JNIEXPORT jlong JNICALL
+Java_com_cangwang_gpuimage_GPUImage_nativeSourceAddTarget(
+ JNIEnv *env,
+ jclass obj,
+ jlong classId,
+ jlong targetClassId,
+ jint texID,
+ jboolean isFilter)
+{
+ Source* source = (Source *) classId;
+ Target* target = isFilter ? dynamic_cast((Filter*)targetClassId) : (Target*)targetClassId;
+ if (texID >= 0) {
+ return (uintptr_t) (source->addTarget(target, texID));
+ } else {
+ return (uintptr_t) (source->addTarget(target));
+ }
+};
+
+JNIEXPORT void JNICALL
+Java_com_cangwang_gpuimage_GPUImage_nativeSourceRemoveTarget(
+ JNIEnv *env,
+ jclass obj,
+ jlong classId,
+ jlong targetClassId,
+ jboolean isFilter)
+{
+ Source* source = (Source *) classId;
+ Target* target = isFilter ? dynamic_cast((Filter*)targetClassId) : (Target*)targetClassId;
+ source->removeTarget(target);
+};
+
+JNIEXPORT void JNICALL
+Java_com_cangwang_gpuimage_GPUImage_nativeSourceRemoveAllTargets(
+ JNIEnv *env,
+ jclass obj,
+ jlong classId)
+{
+ ((Source *) classId)->removeAllTargets();
+};
+
+JNIEXPORT jlong JNICALL
+Java_com_cangwang_gpuimage_GPUImage_nativeSourceProceed(
+ JNIEnv *env,
+ jclass obj,
+ jlong classId,
+ jboolean bUpdateTargets )
+{
+ return ((Source *) classId)->proceed(bUpdateTargets);
+};
+
+JNIEXPORT jint JNICALL
+Java_com_cangwang_gpuimage_GPUImage_nativeSourceGetRotatedFramebuferWidth(
+ JNIEnv *env,
+ jclass obj,
+ jlong classId)
+{
+ return ((Source *) classId)->getRotatedFramebufferWidth();
+};
+
+JNIEXPORT jint JNICALL
+Java_com_cangwang_gpuimage_GPUImage_nativeSourceGetRotatedFramebuferHeight(
+ JNIEnv *env,
+ jclass,
+ jlong classId)
+{
+ return ((Source *) classId)->getRotatedFramebufferHeight();
+};
+
+JNIEXPORT jbyteArray JNICALL
+Java_com_cangwang_gpuimage_GPUImage_nativeSourceCaptureAProcessedFrameData(
+ JNIEnv *env,
+ jclass obj,
+ jlong classId,
+ jlong upToFilterClassId,
+ jint width,
+ jint height )
+{
+ unsigned char* processedFrameData = ((Source *) classId)->captureAProcessedFrameData((Filter*)upToFilterClassId, width, height);
+ int frameSize = width * height * 4 * sizeof(unsigned char);
+
+ jbyteArray jresult = NULL;
+ if (processedFrameData) {
+ jbyte* by = (jbyte*)processedFrameData;
+ jresult = env->NewByteArray(frameSize);
+ env->SetByteArrayRegion(jresult, 0, frameSize, by);
+ delete[] processedFrameData;
+ processedFrameData = 0;
+ }
+
+ return jresult;
+};
+
+JNIEXPORT jlong JNICALL
+Java_com_cangwang_gpuimage_GPUImage_nativeTargetViewNew(
+ JNIEnv *env,
+ jclass obj)
+{
+ return (uintptr_t)(new TargetView());
+};
+
+JNIEXPORT void JNICALL
+Java_com_cangwang_gpuimage_GPUImage_nativeTargetViewFinalize(
+ JNIEnv *env,
+ jclass obj,
+ jlong classId)
+{
+ ((TargetView*)classId)->release();
+};
+
+JNIEXPORT void JNICALL
+Java_com_cangwang_gpuimage_GPUImage_nativeTargetViewOnSizeChanged(
+ JNIEnv *env,
+ jclass obj,
+ jlong classId,
+ jint width,
+ jint height)
+{
+ ((TargetView*)classId)->onSizeChanged(width, height);
+};
+
+JNIEXPORT void JNICALL
+Java_com_cangwang_gpuimage_GPUImage_nativeTargetViewSetFillMode(
+ JNIEnv *env,
+ jclass obj,
+ jlong classId,
+ jint fillMode)
+{
+ ((TargetView*)classId)->setFillMode((TargetView::FillMode)fillMode);
+};
+
+JNIEXPORT jlong JNICALL
+Java_com_cangwang_gpuimage_GPUImage_nativeFilterCreate(
+ JNIEnv *env,
+ jclass obj,
+ jstring jFilterClassName)
+{
+ const char* filterClassName = env->GetStringUTFChars(jFilterClassName, 0);
+ long ret = (uintptr_t)(Filter::create(filterClassName));
+ env->ReleaseStringUTFChars(jFilterClassName, filterClassName);
+ return ret;
+};
+
+JNIEXPORT void JNICALL
+Java_com_cangwang_gpuimage_GPUImage_nativeFilterDestroy(
+ JNIEnv *env,
+ jclass obj,
+ jlong classId)
+{
+ ((Filter*)classId)->release();
+};
+
+JNIEXPORT void JNICALL
+Java_com_cangwang_gpuimage_GPUImage_nativeFilterFinalize(
+ JNIEnv *env,
+ jclass obj,
+ jlong classId)
+{
+ ((Filter*)classId)->releaseFramebuffer(false);
+ ((Filter*)classId)->release();
+};
+
+JNIEXPORT void JNICALL
+Java_com_cangwang_gpuimage_GPUImage_nativeFilterSetPropertyFloat(
+ JNIEnv *env,
+ jclass obj,
+ jlong classId,
+ jstring jProperty,
+ jfloat value)
+{
+ const char* property = env->GetStringUTFChars(jProperty, 0);
+ ((Filter*)classId)->setProperty(property, value);
+ env->ReleaseStringUTFChars(jProperty, property);
+
+};
+
+JNIEXPORT void JNICALL
+Java_com_cangwang_gpuimage_GPUImage_nativeFilterSetPropertyInt(
+ JNIEnv *env,
+ jclass obj,
+ jlong classId,
+ jstring jProperty,
+ jint value)
+{
+ const char* property = env->GetStringUTFChars(jProperty, 0);
+ ((Filter*)classId)->setProperty(property, value);
+ env->ReleaseStringUTFChars(jProperty, property);
+
+};
+
+JNIEXPORT void JNICALL
+Java_com_cangwang_gpuimage_GPUImage_nativeFilterSetPropertyString(
+ JNIEnv *env,
+ jclass obj,
+ jlong classId,
+ jstring jProperty,
+ jstring jValue)
+{
+ const char* property = env->GetStringUTFChars(jProperty, 0);
+ const char* value = env->GetStringUTFChars(jValue, 0);
+ ((Filter*)classId)->setProperty(property, value);
+ env->ReleaseStringUTFChars(jProperty, property);
+ env->ReleaseStringUTFChars(jValue, value);
+
+};
+
+JNIEXPORT void JNICALL
+Java_com_cangwang_gpuimage_GPUImage_nativeContextInit(
+ JNIEnv *env,
+ jclass obj)
+{
+ Context::init();
+};
+
+JNIEXPORT void JNICALL
+Java_com_cangwang_gpuimage_GPUImage_nativeContextDestroy(
+ JNIEnv *env,
+ jclass obj)
+{
+ Context::destroy();
+};
+
+JNIEXPORT void JNICALL
+Java_com_cangwang_gpuimage_GPUImage_nativeContextPurge(
+ JNIEnv *env,
+ jclass obj)
+{
+ Context::getInstance()->purge();
+};
+
+JNIEXPORT void JNICALL
+Java_com_cangwang_gpuimage_GPUImage_nativeYUVtoRBGA(JNIEnv * env, jclass obj, jbyteArray yuv420sp, jint width, jint height, jintArray rgbOut)
+{
+ int sz;
+ int i;
+ int j;
+ int Y;
+ int Cr = 0;
+ int Cb = 0;
+ int pixPtr = 0;
+ int jDiv2 = 0;
+ int R = 0;
+ int G = 0;
+ int B = 0;
+ int cOff;
+ int w = width;
+ int h = height;
+ sz = w * h;
+
+ jint *rgbData = (jint*) (env->GetPrimitiveArrayCritical(rgbOut, 0));
+ jbyte* yuv = (jbyte*) env->GetPrimitiveArrayCritical(yuv420sp, 0);
+
+ for(j = 0; j < h; j++) {
+ pixPtr = j * w;
+ jDiv2 = j >> 1;
+ for(i = 0; i < w; i++) {
+ Y = yuv[pixPtr];
+ if(Y < 0) Y += 255;
+ if((i & 0x1) != 1) {
+ cOff = sz + jDiv2 * w + (i >> 1) * 2;
+ Cb = yuv[cOff];
+ if(Cb < 0) Cb += 127; else Cb -= 128;
+ Cr = yuv[cOff + 1];
+ if(Cr < 0) Cr += 127; else Cr -= 128;
+ }
+
+ //ITU-R BT.601 conversion
+ //
+ //R = 1.164*(Y-16) + 2.018*(Cr-128);
+ //G = 1.164*(Y-16) - 0.813*(Cb-128) - 0.391*(Cr-128);
+ //B = 1.164*(Y-16) + 1.596*(Cb-128);
+ //
+ Y = Y + (Y >> 3) + (Y >> 5) + (Y >> 7);
+ R = Y + (Cr << 1) + (Cr >> 6);
+ if(R < 0) R = 0; else if(R > 255) R = 255;
+ G = Y - Cb + (Cb >> 3) + (Cb >> 4) - (Cr >> 1) + (Cr >> 3);
+ if(G < 0) G = 0; else if(G > 255) G = 255;
+ B = Y + Cb + (Cb >> 1) + (Cb >> 4) + (Cb >> 5);
+ if(B < 0) B = 0; else if(B > 255) B = 255;
+ rgbData[pixPtr++] = 0xff000000 + (R << 16) + (G << 8) + B;
+ }
+ }
+
+ env->ReleasePrimitiveArrayCritical(rgbOut, rgbData, 0);
+ env->ReleasePrimitiveArrayCritical(yuv420sp, yuv, 0);
+}
+
+}
+
+#endif
\ No newline at end of file
diff --git a/app/src/main/cpp/bitmap/BitmapOperation.cpp b/filter/src/main/cpp/bitmap/BitmapOperation.cpp
similarity index 100%
rename from app/src/main/cpp/bitmap/BitmapOperation.cpp
rename to filter/src/main/cpp/bitmap/BitmapOperation.cpp
diff --git a/app/src/main/cpp/bitmap/BitmapOperation.h b/filter/src/main/cpp/bitmap/BitmapOperation.h
similarity index 100%
rename from app/src/main/cpp/bitmap/BitmapOperation.h
rename to filter/src/main/cpp/bitmap/BitmapOperation.h
diff --git a/app/src/main/cpp/bitmap/JniBitmap.h b/filter/src/main/cpp/bitmap/JniBitmap.h
similarity index 100%
rename from app/src/main/cpp/bitmap/JniBitmap.h
rename to filter/src/main/cpp/bitmap/JniBitmap.h
diff --git a/app/src/main/cpp/camera/CameraEngine.cpp b/filter/src/main/cpp/camera/CameraEngine.cpp
similarity index 98%
rename from app/src/main/cpp/camera/CameraEngine.cpp
rename to filter/src/main/cpp/camera/CameraEngine.cpp
index 21eae43..ec4053a 100644
--- a/app/src/main/cpp/camera/CameraEngine.cpp
+++ b/filter/src/main/cpp/camera/CameraEngine.cpp
@@ -1,7 +1,7 @@
#include
#include
#include "CameraEngine.h"
-#include "src/main/cpp/utils/OpenglUtils.h"
+#include "utils/OpenglUtils.h"
#include
#include
#include
@@ -59,7 +59,7 @@ CameraEngine::~CameraEngine() {
}
int CameraEngine::create() {
- if (!mEGLCore->buildContext(mWindow)){
+ if (!mEGLCore->buildContext(mWindow,EGL_NO_CONTEXT)){
return -1;
}
std::string *vShader = readShaderFromAsset(mAssetManager,"camera.vert");
diff --git a/app/src/main/cpp/camera/CameraEngine.h b/filter/src/main/cpp/camera/CameraEngine.h
similarity index 78%
rename from app/src/main/cpp/camera/CameraEngine.h
rename to filter/src/main/cpp/camera/CameraEngine.h
index 198cbed..0e006e0 100644
--- a/app/src/main/cpp/camera/CameraEngine.h
+++ b/filter/src/main/cpp/camera/CameraEngine.h
@@ -3,11 +3,11 @@
#include
#include
#include
-#include
-#include "src/main/cpp/utils/OpenglUtils.h"
+#include
+#include "utils/OpenglUtils.h"
#include
-#include "src/main/cpp/egl/EGLCore.h"
-#include "src/main/cpp/egl/GLBase.h"
+#include "egl/EGLCore.h"
+#include "egl/GLBase.h"
/**
* cangwang 2018.12.1
diff --git a/app/src/main/cpp/camera/CameraFilter.cpp b/filter/src/main/cpp/camera/CameraFilter.cpp
similarity index 79%
rename from app/src/main/cpp/camera/CameraFilter.cpp
rename to filter/src/main/cpp/camera/CameraFilter.cpp
index 269f35e..54a1113 100644
--- a/app/src/main/cpp/camera/CameraFilter.cpp
+++ b/filter/src/main/cpp/camera/CameraFilter.cpp
@@ -1,16 +1,13 @@
#include
#include
#include "CameraFilter.h"
-#include "src/main/cpp/utils/OpenglUtils.h"
+#include "utils/OpenglUtils.h"
#include
#include
#include
-#include
-#include
-#include
-#include
-#include
-#include
+#include
+#include
+#include
#define LOG_TAG "CameraFilter"
@@ -21,26 +18,6 @@
* 相机滤镜管理
* cangwang 2018.12.1
*/
-const static GLfloat VERTICES[]= {
- -1.0f,1.0f,
- 1.0f,1.0f,
- -1.0f,-1.0f,
- 1.0f,-1.0f
-};
-
-const static GLfloat TEX_COORDS[]={
- 0.0f,1.0f,
- 1.0f,1.0f,
- 0.0f,0.0f,
- 1.0f,0.0f
-};
-
-const static GLuint ATTRIB_POSITION = 0;
-const static GLuint ATTRIB_TEXCOORD = 1;
-const static GLuint VERTEX_NUM = 4;
-const static GLuint VERTEX_POS_SIZE = 2;
-const static GLuint TEX_COORD_POS_SZIE = 2;
-
CameraFilter::CameraFilter(ANativeWindow *window): mWindow(window),mEGLCore(new EGLCore()),
mAssetManager(nullptr),mTextureId(0),mTextureLoc(0),
mMatrixLoc(0){
@@ -52,9 +29,10 @@ CameraFilter::CameraFilter(ANativeWindow *window): mWindow(window),mEGLCore(new
mMatrix[15] = 1;
}
-CameraFilter::CameraFilter(ANativeWindow *window,AAssetManager* assetManager): mWindow(window),mEGLCore(new EGLCore()),
+CameraFilter::CameraFilter(ANativeWindow *window,AAssetManager* assetManager): mWindow(window),mEGLCore(new EGLCore()), mVideoWindow(nullptr),
mAssetManager(assetManager),mTextureId(0),mTextureLoc(0),
- mMatrixLoc(0),filter(nullptr),cameraInputFilter(nullptr){
+ mMatrixLoc(0),filter(nullptr),cameraInputFilter(nullptr),
+ pool(new std::MagicThreadPool()){
//清空mMatrix数组
memset(mMatrix,0, sizeof(mMatrix));
mMatrix[0] = 1;
@@ -94,17 +72,16 @@ CameraFilter::~CameraFilter() {
}
mAssetManager = nullptr;
+ //释放线程池
+ free(pool);
}
void CameraFilter::setFilter(AAssetManager* assetManager) {
-// if (cameraInputFilter == nullptr){
-// cameraInputFilter = new CameraInputFilter(assetManager);
-// }
if(filter != nullptr){
filter->destroy();
}
-// filter = new MagicAmaroFilter(assetManager);
filter = new MagicNoneFilter(assetManager);
+ filter->setPool(pool);
ALOGD("set filter success");
}
@@ -119,7 +96,7 @@ int CameraFilter::create() {
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
- if (!mEGLCore->buildContext(mWindow)){
+ if (!mEGLCore->buildContext(mWindow,EGL_NO_CONTEXT)){
return -1;
}
@@ -172,7 +149,8 @@ void CameraFilter::draw(GLfloat *matrix) {
filter->onDrawFrame(id,matrix);
//缓冲区交换
glFlush();
- mEGLCore->swapBuffer();
+ if(mEGLCore!= nullptr)
+ mEGLCore->swapBuffer();
}
}
@@ -187,6 +165,7 @@ void CameraFilter::setFilter(GPUImageFilter* gpuImageFilter) {
filter= nullptr;
}
filter = gpuImageFilter;
+ filter->setPool(pool);
ALOGD("set filter success");
if (filter!= nullptr)
filter->init();
@@ -204,4 +183,12 @@ bool CameraFilter::savePhoto(std::string saveFileAddress){
return filter->savePhoto(saveFileAddress);
}
return false;
-}
\ No newline at end of file
+}
+
+EGLContext CameraFilter::getCurrentContext() {
+ if (mEGLCore!= nullptr){
+ return mEGLCore->getCurrent();
+ }
+ return nullptr;
+}
+
diff --git a/app/src/main/cpp/camera/CameraFilter.h b/filter/src/main/cpp/camera/CameraFilter.h
similarity index 78%
rename from app/src/main/cpp/camera/CameraFilter.h
rename to filter/src/main/cpp/camera/CameraFilter.h
index 018057c..f688836 100644
--- a/app/src/main/cpp/camera/CameraFilter.h
+++ b/filter/src/main/cpp/camera/CameraFilter.h
@@ -3,12 +3,12 @@
#include
#include
#include
-#include "src/main/cpp/utils/OpenglUtils.h"
-#include "src/main/cpp/egl/GLBase.h"
-#include "src/main/cpp/egl/EGLCore.h"
+#include "utils/OpenglUtils.h"
+#include "egl/GLBase.h"
+#include "egl/EGLCore.h"
#include
-#include
-#include
+#include
+#include
#include
/**
@@ -28,6 +28,7 @@ class CameraFilter:public GLBase{
void setFilter(int type);
void setBeautyLevel(int level);
bool savePhoto(std::string saveFileAddress);
+ EGLContext getCurrentContext();
protected:
@@ -36,10 +37,12 @@ class CameraFilter:public GLBase{
CameraInputFilter *cameraInputFilter;
AAssetManager *mAssetManager;
ANativeWindow *mWindow;
+ ANativeWindow *mVideoWindow;
GLuint mTextureId;
GLint mTextureLoc;
GLint mMatrixLoc;
GLfloat mMatrix[16];
EGLCore *mEGLCore;
+ std::MagicThreadPool *pool;
};
diff --git a/filter/src/main/cpp/effect/BeautifyFilter.cpp b/filter/src/main/cpp/effect/BeautifyFilter.cpp
new file mode 100755
index 0000000..cc90f94
--- /dev/null
+++ b/filter/src/main/cpp/effect/BeautifyFilter.cpp
@@ -0,0 +1,182 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include "BeautifyFilter.hpp"
+
+
+NS_GI_BEGIN
+
+
+// Beautify shader code is adapted from guikz's beautify filter demo
+// reference :
+// http://www.csie.ntu.edu.tw/~fuh/personal/FaceBeautificationandColorEnhancement.A2-1-0040.pdf
+// http://m.blog.csdn.net/article/details?id=50496969
+const std::string kBeautifyCombinationFragmentShaderString = SHADER_STRING
+(
+ varying highp vec2 vTexCoord;
+ varying highp vec2 vTexCoord1;
+ varying highp vec2 vTexCoord2;
+
+ uniform sampler2D colorMap;
+ uniform sampler2D colorMap1;
+ uniform sampler2D colorMap2;
+ uniform mediump float smoothDegree;
+
+ void main()
+ {
+ highp vec4 bilateral = texture2D(colorMap, vTexCoord);
+ highp vec4 canny = texture2D(colorMap1, vTexCoord1);
+
+ highp vec4 origin = texture2D(colorMap2,vTexCoord2);
+ highp vec4 smooth;
+ lowp float r = origin.r;
+ lowp float g = origin.g;
+ lowp float b = origin.b;
+
+ if (canny.r < 0.2 && r > 0.3725 && g > 0.1568 && b > 0.0784 && r > b && (max(max(r, g), b) - min(min(r, g), b)) > 0.0588 && abs(r-g) > 0.0588) {
+ smooth = (1.0 - smoothDegree) * (origin - bilateral) + bilateral;
+ }
+ else {
+ smooth = origin;
+ }
+
+ smooth.r = log(1.0 + 0.2 * smooth.r)/log(1.2);
+ smooth.g = log(1.0 + 0.2 * smooth.g)/log(1.2);
+ smooth.b = log(1.0 + 0.2 * smooth.b)/log(1.2);
+ gl_FragColor = smooth;
+ //gl_FragColor = origin;
+ }
+ );
+
+class CombinationFilter : public Filter {
+public:
+ static CombinationFilter* create() {
+ CombinationFilter* ret = new (std::nothrow) CombinationFilter();
+ if (!ret || !ret->init()) {
+ delete ret;
+ ret = 0;
+ }
+ return ret;
+ }
+
+ bool init() {
+ if (!Filter::initWithFragmentShaderString(kBeautifyCombinationFragmentShaderString, 3)) {
+ return false;
+ }
+ _intensity = 0.5;
+
+ return true;
+ }
+
+ virtual bool proceed(bool bUpdateTargets = true) override {
+ _filterProgram->setUniformValue("smoothDegree", _intensity);
+ return Filter::proceed(bUpdateTargets);
+ }
+
+protected:
+ CombinationFilter() {};
+
+private:
+ float _intensity;
+};
+
+REGISTER_FILTER_CLASS(BeautifyFilter)
+
+BeautifyFilter::BeautifyFilter()
+:_bilateralFilter(0)
+,_cannyEdgeDetectionFilter(0)
+,_combinationFilter(0)
+,_hsbFilter(0)
+{
+}
+
+BeautifyFilter::~BeautifyFilter() {
+ if (_bilateralFilter) {
+ _bilateralFilter->release();
+ _bilateralFilter = 0;
+ }
+ if (_cannyEdgeDetectionFilter) {
+ _cannyEdgeDetectionFilter->release();
+ _cannyEdgeDetectionFilter = 0;
+ }
+ if (_combinationFilter) {
+ _combinationFilter->release();
+ _combinationFilter = 0;
+ }
+ if (_hsbFilter) {
+ _hsbFilter->release();
+ _hsbFilter = 0;
+ }
+}
+
+BeautifyFilter* BeautifyFilter::create() {
+ BeautifyFilter* ret = new (std::nothrow) BeautifyFilter();
+ if (ret && !ret->init()) {
+ delete ret;
+ ret = 0;
+ }
+ return ret;
+}
+
+bool BeautifyFilter::init() {
+ if (!FilterGroup::init()) {
+ return false;
+ }
+
+ // 1. face smoothing
+ _bilateralFilter = BilateralFilter::create();
+ _bilateralFilter->setDistanceNormalizationFactor(4.0);
+ addFilter(_bilateralFilter);
+
+ // 2. edge detection
+ _cannyEdgeDetectionFilter = CannyEdgeDetectionFilter::create();
+ addFilter(_cannyEdgeDetectionFilter);
+
+ // 3.combination bilateral, edge detection and origin
+ _combinationFilter = CombinationFilter::create();
+ addFilter(_combinationFilter);
+
+ _bilateralFilter->addTarget(_combinationFilter);
+ _cannyEdgeDetectionFilter->addTarget(_combinationFilter);
+
+ // 4. adjust hsb
+ _hsbFilter = HSBFilter::create();
+ _hsbFilter->adjustBrightness(1.1);
+ _hsbFilter->adjustSaturation(1.1);
+ _combinationFilter->addTarget(_hsbFilter);
+
+ setTerminalFilter(_hsbFilter);
+
+ return true;
+}
+
+
+bool BeautifyFilter::proceed(bool bUpdateTargets/* = true*/) {
+ return FilterGroup::proceed(bUpdateTargets);
+}
+
+
+void BeautifyFilter::setInputFramebuffer(Framebuffer* framebuffer, RotationMode rotationMode/* = NoRotation*/, int texIdx/* = 0*/) {
+ for (auto& filter : _filters) {
+ if (filter == _combinationFilter)
+ texIdx = 2;
+ filter->setInputFramebuffer(framebuffer, rotationMode, texIdx);
+ }
+}
+
+NS_GI_END
diff --git a/filter/src/main/cpp/effect/BeautifyFilter.hpp b/filter/src/main/cpp/effect/BeautifyFilter.hpp
new file mode 100755
index 0000000..31efd78
--- /dev/null
+++ b/filter/src/main/cpp/effect/BeautifyFilter.hpp
@@ -0,0 +1,54 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef BeautifyFilter_hpp
+#define BeautifyFilter_hpp
+
+#include "../source/macros.h"
+#include "FilterGroup.hpp"
+#include "BilateralFilter.hpp"
+#include "CannyEdgeDetectionFilter.hpp"
+#include "ColorInvertFilter.hpp"
+#include "GrayscaleFilter.hpp"
+#include "HSBFilter.hpp"
+
+NS_GI_BEGIN
+
+class CombinationFilter;
+
+class BeautifyFilter : public FilterGroup {
+public:
+ static BeautifyFilter* create();
+ bool init();
+ bool proceed(bool bUpdateTargets = true) override;
+
+ virtual void setInputFramebuffer(Framebuffer* framebuffer, RotationMode rotationMode = NoRotation, int texIdx = 0) override;
+
+protected:
+ BeautifyFilter();
+ ~BeautifyFilter();
+
+ BilateralFilter* _bilateralFilter;
+ CannyEdgeDetectionFilter* _cannyEdgeDetectionFilter;
+ CombinationFilter* _combinationFilter;
+ HSBFilter* _hsbFilter;
+};
+
+NS_GI_END
+
+#endif /* BeautifyFilter_hpp */
diff --git a/filter/src/main/cpp/effect/BilateralFilter.cpp b/filter/src/main/cpp/effect/BilateralFilter.cpp
new file mode 100755
index 0000000..b1e990e
--- /dev/null
+++ b/filter/src/main/cpp/effect/BilateralFilter.cpp
@@ -0,0 +1,244 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include "BilateralFilter.hpp"
+
+NS_GI_BEGIN
+
+REGISTER_FILTER_CLASS(BilateralMonoFilter)
+
+const std::string kBilateralBlurVertexShaderString = SHADER_STRING
+(
+ attribute vec4 position;
+ attribute vec4 texCoord;
+
+ const int GAUSSIAN_SAMPLES = 9;
+
+ uniform float texelSpacingU;
+ uniform float texelSpacingV;
+
+ varying vec2 blurCoordinates[GAUSSIAN_SAMPLES];
+
+ void main()
+ {
+ gl_Position = position;
+ vec2 texelSpacing = vec2(texelSpacingU, texelSpacingV);
+ for (int i = 0; i < GAUSSIAN_SAMPLES; i++)
+ {
+ blurCoordinates[i] = texCoord.xy + texelSpacing * float((i - ((GAUSSIAN_SAMPLES - 1) / 2)));
+ }
+ }
+ );
+
+const std::string kBilateralBlurFragmentShaderString = SHADER_STRING
+(
+ uniform sampler2D colorMap;
+
+ const lowp int GAUSSIAN_SAMPLES = 9;
+
+ varying highp vec2 blurCoordinates[GAUSSIAN_SAMPLES];
+
+ uniform mediump float distanceNormalizationFactor;
+
+ void main()
+ {
+ lowp vec4 centralColor;
+ lowp float gaussianWeightTotal;
+ lowp vec4 sum;
+ lowp vec4 sampleColor;
+ lowp float distanceFromCentralColor;
+ lowp float gaussianWeight;
+
+ centralColor = texture2D(colorMap, blurCoordinates[4]);
+ gaussianWeightTotal = 0.18;
+ sum = centralColor * 0.18;
+
+ sampleColor = texture2D(colorMap, blurCoordinates[0]);
+ distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
+ gaussianWeight = 0.05 * (1.0 - distanceFromCentralColor);
+ gaussianWeightTotal += gaussianWeight;
+ sum += sampleColor * gaussianWeight;
+
+ sampleColor = texture2D(colorMap, blurCoordinates[1]);
+ distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
+ gaussianWeight = 0.09 * (1.0 - distanceFromCentralColor);
+ gaussianWeightTotal += gaussianWeight;
+ sum += sampleColor * gaussianWeight;
+
+ sampleColor = texture2D(colorMap, blurCoordinates[2]);
+ distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
+ gaussianWeight = 0.12 * (1.0 - distanceFromCentralColor);
+ gaussianWeightTotal += gaussianWeight;
+ sum += sampleColor * gaussianWeight;
+
+ sampleColor = texture2D(colorMap, blurCoordinates[3]);
+ distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
+ gaussianWeight = 0.15 * (1.0 - distanceFromCentralColor);
+ gaussianWeightTotal += gaussianWeight;
+ sum += sampleColor * gaussianWeight;
+
+ sampleColor = texture2D(colorMap, blurCoordinates[5]);
+ distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
+ gaussianWeight = 0.15 * (1.0 - distanceFromCentralColor);
+ gaussianWeightTotal += gaussianWeight;
+ sum += sampleColor * gaussianWeight;
+
+ sampleColor = texture2D(colorMap, blurCoordinates[6]);
+ distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
+ gaussianWeight = 0.12 * (1.0 - distanceFromCentralColor);
+ gaussianWeightTotal += gaussianWeight;
+ sum += sampleColor * gaussianWeight;
+
+ sampleColor = texture2D(colorMap, blurCoordinates[7]);
+ distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
+ gaussianWeight = 0.09 * (1.0 - distanceFromCentralColor);
+ gaussianWeightTotal += gaussianWeight;
+ sum += sampleColor * gaussianWeight;
+
+ sampleColor = texture2D(colorMap, blurCoordinates[8]);
+ distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
+ gaussianWeight = 0.05 * (1.0 - distanceFromCentralColor);
+ gaussianWeightTotal += gaussianWeight;
+ sum += sampleColor * gaussianWeight;
+
+ gl_FragColor = sum / gaussianWeightTotal;
+ }
+ );
+
+ BilateralMonoFilter::BilateralMonoFilter(Type type)
+ :_type(type)
+,_texelSpacingMultiplier(4.0)
+,_distanceNormalizationFactor(8.0)
+ {
+
+ }
+
+ BilateralMonoFilter* BilateralMonoFilter::create(Type type/* = HORIZONTAL*/) {
+ BilateralMonoFilter* ret = new (std::nothrow) BilateralMonoFilter(type);
+ if (!ret || !ret->init()) {
+ delete ret;
+ ret = 0;
+ }
+ return ret;
+ }
+
+bool BilateralMonoFilter::init() {
+ if (Filter::initWithShaderString(kBilateralBlurVertexShaderString, kBilateralBlurFragmentShaderString)) {
+ return true;
+ }
+ return false;
+}
+
+bool BilateralMonoFilter::proceed(bool bUpdateTargets/* = true*/) {
+ Framebuffer* inputFramebuffer = _inputFramebuffers.begin()->second.frameBuffer;
+ RotationMode inputRotation = _inputFramebuffers.begin()->second.rotationMode;
+
+ if (rotationSwapsSize(inputRotation))
+ {
+ if (_type == HORIZONTAL) {
+ _filterProgram->setUniformValue("texelSpacingU", (float)0.0);
+ _filterProgram->setUniformValue("texelSpacingV", (float)(_texelSpacingMultiplier / _framebuffer->getWidth()));
+ } else {
+ _filterProgram->setUniformValue("texelSpacingU", (float)(_texelSpacingMultiplier / _framebuffer->getHeight()));
+ _filterProgram->setUniformValue("texelSpacingV", (float)0.0);
+ }
+ } else {
+ if (_type == HORIZONTAL) {
+ _filterProgram->setUniformValue("texelSpacingU", (float)(_texelSpacingMultiplier / _framebuffer->getWidth()));
+ _filterProgram->setUniformValue("texelSpacingV", (float)0.0);
+ } else {
+ _filterProgram->setUniformValue("texelSpacingU", (float)0.0);
+ _filterProgram->setUniformValue("texelSpacingV", (float)(_texelSpacingMultiplier / _framebuffer->getHeight()));
+ }
+ }
+
+
+ _filterProgram->setUniformValue("distanceNormalizationFactor", _distanceNormalizationFactor);
+ return Filter::proceed(bUpdateTargets);
+}
+
+void BilateralMonoFilter::setTexelSpacingMultiplier(float multiplier) {
+ _texelSpacingMultiplier = multiplier;
+}
+
+void BilateralMonoFilter::setDistanceNormalizationFactor(float value) {
+ _distanceNormalizationFactor = value;
+}
+
+REGISTER_FILTER_CLASS(BilateralFilter)
+
+BilateralFilter::BilateralFilter()
+:_hBlurFilter(0)
+,_vBlurFilter(0)
+{
+}
+
+BilateralFilter::~BilateralFilter() {
+ if (_hBlurFilter) {
+ _hBlurFilter->release();
+ _hBlurFilter = 0;
+ }
+
+ if (_vBlurFilter) {
+ _vBlurFilter->release();
+ _vBlurFilter = 0;
+ }
+
+}
+
+BilateralFilter* BilateralFilter::create() {
+ BilateralFilter* ret = new (std::nothrow) BilateralFilter();
+ if (ret && !ret->init()) {
+ delete ret;
+ ret = 0;
+ }
+ return ret;
+}
+
+bool BilateralFilter::init() {
+ if (!FilterGroup::init()) {
+ return false;
+ }
+
+ _hBlurFilter = BilateralMonoFilter::create(BilateralMonoFilter::HORIZONTAL);
+ _vBlurFilter = BilateralMonoFilter::create(BilateralMonoFilter::VERTICAL);
+ _hBlurFilter->addTarget(_vBlurFilter);
+ addFilter(_hBlurFilter);
+
+ registerProperty("texelSpacingMultiplier", 4.0, "The texel spacing multiplier.", [this](float& texelSpacingMultiplier){
+ setTexelSpacingMultiplier(texelSpacingMultiplier);
+ });
+
+ registerProperty("distanceNormalizationFactor", 8.0, "The distance normalization factor.", [this](float& distanceNormalizationFactor){
+ setDistanceNormalizationFactor(distanceNormalizationFactor);
+ });
+
+ return true;
+}
+
+void BilateralFilter::setTexelSpacingMultiplier(float multiplier) {
+ _hBlurFilter->setTexelSpacingMultiplier(multiplier);
+ _vBlurFilter->setTexelSpacingMultiplier(multiplier);
+}
+
+void BilateralFilter::setDistanceNormalizationFactor(float value) {
+ _hBlurFilter->setDistanceNormalizationFactor(value);
+ _vBlurFilter->setDistanceNormalizationFactor(value);
+
+}
+NS_GI_END
diff --git a/filter/src/main/cpp/effect/BilateralFilter.hpp b/filter/src/main/cpp/effect/BilateralFilter.hpp
new file mode 100755
index 0000000..eca6253
--- /dev/null
+++ b/filter/src/main/cpp/effect/BilateralFilter.hpp
@@ -0,0 +1,68 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef BilateralFilter_hpp
+#define BilateralFilter_hpp
+
+#include "../source/macros.h"
+#include "FilterGroup.hpp"
+
+NS_GI_BEGIN
+
+
+class BilateralMonoFilter : public Filter {
+public:
+ enum Type {HORIZONTAL, VERTICAL};
+
+ static BilateralMonoFilter* create(Type type = HORIZONTAL);
+ bool init();
+
+ virtual bool proceed(bool bUpdateTargets = true) override;
+
+ void setTexelSpacingMultiplier(float multiplier);
+ void setDistanceNormalizationFactor(float value);
+protected:
+ BilateralMonoFilter(Type type);
+ Type _type;
+ float _texelSpacingMultiplier;
+ float _distanceNormalizationFactor;
+};
+
+class BilateralFilter : public FilterGroup {
+public:
+ virtual ~BilateralFilter();
+
+ static BilateralFilter* create();
+ bool init();
+
+ void setTexelSpacingMultiplier(float multiplier);
+ void setDistanceNormalizationFactor(float value);
+
+protected:
+ BilateralFilter();
+
+private:
+ //friend BilateralMonoFilter;
+ BilateralMonoFilter* _hBlurFilter;
+ BilateralMonoFilter* _vBlurFilter;
+};
+
+
+NS_GI_END
+
+#endif /* BilateralFilter_hpp */
diff --git a/filter/src/main/cpp/effect/BrightnessFilter.cpp b/filter/src/main/cpp/effect/BrightnessFilter.cpp
new file mode 100755
index 0000000..3d3c7b6
--- /dev/null
+++ b/filter/src/main/cpp/effect/BrightnessFilter.cpp
@@ -0,0 +1,69 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include "BrightnessFilter.hpp"
+
+USING_NS_GI
+
+REGISTER_FILTER_CLASS(BrightnessFilter)
+
+const std::string kBrightnessFragmentShaderString = SHADER_STRING
+(
+ uniform sampler2D colorMap;
+ uniform lowp float brightness;
+ varying highp vec2 vTexCoord;
+
+ void main()
+ {
+ lowp vec4 color = texture2D(colorMap, vTexCoord);
+ gl_FragColor = vec4((color.rgb + vec3(brightness)), color.a);
+ }
+);
+
+
+BrightnessFilter* BrightnessFilter::create(float brightness/* = 0.0*/) {
+ BrightnessFilter* ret = new (std::nothrow) BrightnessFilter();
+ if (ret && !ret->init(brightness)) {
+ delete ret;
+ ret = 0;
+ }
+ return ret;
+}
+
+bool BrightnessFilter::init(float brightness) {
+ if (!initWithFragmentShaderString(kBrightnessFragmentShaderString)) return false;
+
+ _brightness = brightness;
+ registerProperty("brightness", _brightness, "The brightness of filter with range between -1 and 1.", [this](float& brightness){
+ setBrightness(brightness);
+ });
+
+ return true;
+}
+
+void BrightnessFilter::setBrightness(float brightness) {
+ _brightness = brightness;
+ if (_brightness > 1.0) _brightness = 1.0;
+ else if (_brightness < -1.0) _brightness = -1.0;
+}
+
+bool BrightnessFilter::proceed(bool bUpdateTargets/* = true*/) {
+ _filterProgram->setUniformValue("brightness", _brightness);
+ return Filter::proceed(bUpdateTargets);
+}
+
diff --git a/filter/src/main/cpp/effect/BrightnessFilter.hpp b/filter/src/main/cpp/effect/BrightnessFilter.hpp
new file mode 100755
index 0000000..70f2aa3
--- /dev/null
+++ b/filter/src/main/cpp/effect/BrightnessFilter.hpp
@@ -0,0 +1,43 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef BrightnessFilter_hpp
+#define BrightnessFilter_hpp
+
+#include "../source/macros.h"
+#include "Filter.hpp"
+
+NS_GI_BEGIN
+
+class BrightnessFilter : public Filter {
+public:
+ static BrightnessFilter* create(float brightness = 0.0);
+ bool init(float brightness);
+ virtual bool proceed(bool bUpdateTargets = true) override;
+
+ void setBrightness(float brightness);
+
+protected:
+ BrightnessFilter() {};
+
+ float _brightness;
+};
+
+NS_GI_END
+
+#endif /* BrightnessFilter_hpp */
diff --git a/filter/src/main/cpp/effect/CannyEdgeDetectionFilter.cpp b/filter/src/main/cpp/effect/CannyEdgeDetectionFilter.cpp
new file mode 100755
index 0000000..09e6dff
--- /dev/null
+++ b/filter/src/main/cpp/effect/CannyEdgeDetectionFilter.cpp
@@ -0,0 +1,94 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include "CannyEdgeDetectionFilter.hpp"
+
+NS_GI_BEGIN
+
+REGISTER_FILTER_CLASS(CannyEdgeDetectionFilter)
+
+CannyEdgeDetectionFilter::CannyEdgeDetectionFilter()
+:_grayscaleFilter(0)
+,_blurFilter(0)
+,_edgeDetectionFilter(0)
+,_nonMaximumSuppressionFilter(0)
+,_weakPixelInclusionFilter(0)
+{
+}
+
+CannyEdgeDetectionFilter::~CannyEdgeDetectionFilter() {
+ if (_grayscaleFilter) {
+ _grayscaleFilter->release();
+ _grayscaleFilter = 0;
+ }
+ if (_blurFilter) {
+ _blurFilter->release();
+ _blurFilter = 0;
+ }
+ if (_edgeDetectionFilter) {
+ _edgeDetectionFilter->release();
+ _edgeDetectionFilter = 0;
+ }
+ if (_nonMaximumSuppressionFilter) {
+ _nonMaximumSuppressionFilter->release();
+ _nonMaximumSuppressionFilter = 0;
+ }
+ if (_weakPixelInclusionFilter) {
+ _weakPixelInclusionFilter->release();
+ _weakPixelInclusionFilter = 0;
+ }
+}
+
+CannyEdgeDetectionFilter* CannyEdgeDetectionFilter::create() {
+ CannyEdgeDetectionFilter* ret = new (std::nothrow) CannyEdgeDetectionFilter();
+ if (ret && !ret->init()) {
+ delete ret;
+ ret = 0;
+ }
+ return ret;
+}
+
+bool CannyEdgeDetectionFilter::init() {
+ if (!FilterGroup::init()) {
+ return false;
+ }
+
+ // 1. convert image to luminance
+ _grayscaleFilter = GrayscaleFilter::create();
+
+ // 2. apply a varialbe Gaussian blur
+ _blurFilter = SingleComponentGaussianBlurFilter::create();
+
+ // 3. soble edge detection
+ _edgeDetectionFilter = DirectionalSobelEdgeDetectionFilter::create();
+
+ // 4. apply non-maximum suppression
+ _nonMaximumSuppressionFilter = DirectionalNonMaximumSuppressionFilter::create();
+
+ // 5. include weak pixels to complete edges
+ _weakPixelInclusionFilter = WeakPixelInclusionFilter::create();
+
+
+ _grayscaleFilter->addTarget(_blurFilter)->addTarget(_edgeDetectionFilter)->addTarget(_nonMaximumSuppressionFilter)->addTarget(_weakPixelInclusionFilter);
+ addFilter(_grayscaleFilter);
+
+ return true;
+}
+
+
+NS_GI_END
diff --git a/filter/src/main/cpp/effect/CannyEdgeDetectionFilter.hpp b/filter/src/main/cpp/effect/CannyEdgeDetectionFilter.hpp
new file mode 100755
index 0000000..a6614ae
--- /dev/null
+++ b/filter/src/main/cpp/effect/CannyEdgeDetectionFilter.hpp
@@ -0,0 +1,51 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef CannyEdgeDetectionFilter_hpp
+#define CannyEdgeDetectionFilter_hpp
+
+#include "../source/macros.h"
+#include "FilterGroup.hpp"
+#include "GrayscaleFilter.hpp"
+#include "SingleComponentGaussianBlurFilter.hpp"
+#include "DirectionalSobelEdgeDetectionFilter.hpp"
+#include "DirectionalNonMaximumSuppressionFilter.hpp"
+#include "WeakPixelInclusionFilter.hpp"
+
+NS_GI_BEGIN
+
+class CannyEdgeDetectionFilter : public FilterGroup {
+public:
+ static CannyEdgeDetectionFilter* create();
+ bool init();
+
+protected:
+ CannyEdgeDetectionFilter();
+ ~CannyEdgeDetectionFilter();
+
+ GrayscaleFilter* _grayscaleFilter;
+ SingleComponentGaussianBlurFilter* _blurFilter;
+ DirectionalSobelEdgeDetectionFilter* _edgeDetectionFilter;
+ DirectionalNonMaximumSuppressionFilter* _nonMaximumSuppressionFilter;
+ WeakPixelInclusionFilter* _weakPixelInclusionFilter;
+
+};
+
+NS_GI_END
+
+#endif /* CannyEdgeDetectionFilter_hpp */
diff --git a/filter/src/main/cpp/effect/ColorInvertFilter.cpp b/filter/src/main/cpp/effect/ColorInvertFilter.cpp
new file mode 100755
index 0000000..40333b7
--- /dev/null
+++ b/filter/src/main/cpp/effect/ColorInvertFilter.cpp
@@ -0,0 +1,59 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include "ColorInvertFilter.hpp"
+
+NS_GI_BEGIN
+
+REGISTER_FILTER_CLASS(ColorInvertFilter)
+
+const std::string kColorInvertFragmentShaderString = SHADER_STRING
+(
+
+ uniform sampler2D colorMap;
+ varying highp vec2 vTexCoord;
+
+ void main()
+ {
+ lowp vec4 color = texture2D(colorMap, vTexCoord);
+ gl_FragColor = vec4((1.0 - color.rgb), color.a);
+ }
+);
+
+
+ColorInvertFilter* ColorInvertFilter::create() {
+ ColorInvertFilter* ret = new (std::nothrow) ColorInvertFilter();
+ if (ret && !ret->init()) {
+ delete ret;
+ ret = 0;
+ }
+ return ret;
+}
+
+bool ColorInvertFilter::init() {
+ if (!Filter::initWithFragmentShaderString(kColorInvertFragmentShaderString)) return false;
+ return true;
+}
+
+
+bool ColorInvertFilter::proceed(bool bUpdateTargets/* = true*/) {
+ return Filter::proceed(bUpdateTargets);
+}
+
+
+NS_GI_END
diff --git a/filter/src/main/cpp/effect/ColorInvertFilter.hpp b/filter/src/main/cpp/effect/ColorInvertFilter.hpp
new file mode 100755
index 0000000..7610749
--- /dev/null
+++ b/filter/src/main/cpp/effect/ColorInvertFilter.hpp
@@ -0,0 +1,40 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef ColorInvertFilter_hpp
+#define ColorInvertFilter_hpp
+
+#include "../source/macros.h"
+#include "Filter.hpp"
+
+NS_GI_BEGIN
+
+class ColorInvertFilter : public Filter {
+public:
+
+ static ColorInvertFilter* create();
+ bool init();
+
+ virtual bool proceed(bool bUpdateTargets = true) override;
+protected:
+ ColorInvertFilter() {};
+};
+
+NS_GI_END
+
+#endif /* ColorInvertFilter_hpp */
diff --git a/filter/src/main/cpp/effect/ColorMatrixFilter.cpp b/filter/src/main/cpp/effect/ColorMatrixFilter.cpp
new file mode 100755
index 0000000..0f9ba81
--- /dev/null
+++ b/filter/src/main/cpp/effect/ColorMatrixFilter.cpp
@@ -0,0 +1,93 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include "ColorMatrixFilter.hpp"
+
+NS_GI_BEGIN
+
+REGISTER_FILTER_CLASS(ColorMatrixFilter)
+
+const std::string kColorMatrixFragmentShaderString = SHADER_STRING
+(
+ uniform sampler2D colorMap;
+ uniform lowp mat4 colorMatrix;
+ uniform lowp float intensity;
+
+ varying highp vec2 vTexCoord;
+
+ void main()
+ {
+ lowp vec4 textureColor = texture2D(colorMap, vTexCoord);
+ lowp vec4 outputColor = textureColor * colorMatrix;
+
+ gl_FragColor = (intensity * outputColor) + ((1.0 - intensity) * textureColor);
+ }
+);
+
+
+const std::string kBrightnessFragmentShaderString = SHADER_STRING
+(
+ uniform sampler2D colorMap;
+ uniform lowp float brightness;
+ varying highp vec2 vTexCoord;
+
+ void main()
+ {
+ lowp vec4 color = texture2D(colorMap, vTexCoord);
+ gl_FragColor = vec4((color.rgb + vec3(brightness)), color.w);
+ }
+ );
+
+ColorMatrixFilter::ColorMatrixFilter()
+:_intensity(1.0)
+,_colorMatrix(Matrix4::IDENTITY)
+{
+
+}
+
+ColorMatrixFilter* ColorMatrixFilter::create() {
+ ColorMatrixFilter* ret = new (std::nothrow) ColorMatrixFilter();
+ if (ret && !ret->init()) {
+ delete ret;
+ ret = 0;
+ }
+ return ret;
+}
+
+bool ColorMatrixFilter::init() {
+ if ( !Filter::initWithFragmentShaderString(kColorMatrixFragmentShaderString)) return false;
+
+ registerProperty("intensity", _intensity, "The percentage of color applied by color matrix with range between 0 and 1.", [this](float& intensity){
+ if (intensity > 1.0) intensity = 1.0;
+ else if (intensity < 0.0) intensity = 0.0;
+ setIntensity(1.0);
+ });
+
+ // todo register paoperty of color matrix
+
+ return true;
+}
+
+bool ColorMatrixFilter::proceed(bool bUpdateTargets/* = true*/) {
+ _filterProgram->setUniformValue("intensity", _intensity);
+ _filterProgram->setUniformValue("colorMatrix", _colorMatrix);
+ return Filter::proceed(bUpdateTargets);
+}
+
+
+NS_GI_END
diff --git a/filter/src/main/cpp/effect/ColorMatrixFilter.hpp b/filter/src/main/cpp/effect/ColorMatrixFilter.hpp
new file mode 100755
index 0000000..d6d4fce
--- /dev/null
+++ b/filter/src/main/cpp/effect/ColorMatrixFilter.hpp
@@ -0,0 +1,49 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef ColorMatrixFilter_hpp
+#define ColorMatrixFilter_hpp
+
+#include "../source/macros.h"
+#include "Filter.hpp"
+#include "../source/math.hpp"
+
+NS_GI_BEGIN
+
+
+class ColorMatrixFilter : public Filter {
+public:
+ static ColorMatrixFilter* create();
+ bool init();
+
+ virtual bool proceed(bool bUpdateTargets = true) override;
+
+ void setIntensity(float intensity) { _intensity = intensity; }
+ void setColorMatrix(Matrix4 colorMatrix) { _colorMatrix = colorMatrix; }
+
+protected:
+ ColorMatrixFilter();
+
+ float _intensity;
+ Matrix4 _colorMatrix;
+};
+
+
+NS_GI_END
+
+#endif /* ColorMatrixFilter_hpp */
diff --git a/filter/src/main/cpp/effect/ContrastFilter.cpp b/filter/src/main/cpp/effect/ContrastFilter.cpp
new file mode 100755
index 0000000..07f6668
--- /dev/null
+++ b/filter/src/main/cpp/effect/ContrastFilter.cpp
@@ -0,0 +1,69 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include "ContrastFilter.hpp"
+
+USING_NS_GI
+
+REGISTER_FILTER_CLASS(ContrastFilter)
+
+const std::string kContrastFragmentShaderString = SHADER_STRING
+(
+ uniform sampler2D colorMap;
+ uniform lowp float contrast;
+ varying highp vec2 vTexCoord;
+
+ void main()
+ {
+ lowp vec4 color = texture2D(colorMap, vTexCoord);
+ gl_FragColor = vec4(((color.rgb - vec3(0.5)) * contrast + vec3(0.5)), color.a);
+ }
+);
+
+
+ContrastFilter* ContrastFilter::create() {
+ ContrastFilter* ret = new (std::nothrow) ContrastFilter();
+ if (ret && !ret->init()) {
+ delete ret;
+ ret = 0;
+ }
+ return ret;
+}
+
+bool ContrastFilter::init() {
+ if (!initWithFragmentShaderString(kContrastFragmentShaderString)) return false;
+
+ _contrast = 1.0;
+ registerProperty("contrast", _contrast, "The contrast of the image. Contrast ranges from 0.0 to 4.0 (max contrast), with 1.0 as the normal level", [this](float& contrast){
+ setContrast(contrast);
+ });
+
+ return true;
+}
+
+void ContrastFilter::setContrast(float contrast) {
+ _contrast = contrast;
+ if (_contrast > 4.0) _contrast = 4.0;
+ else if (_contrast < 0.0) _contrast = 0.0;
+}
+
+bool ContrastFilter::proceed(bool bUpdateTargets/* = true*/) {
+ _filterProgram->setUniformValue("contrast", _contrast);
+ return Filter::proceed(bUpdateTargets);
+}
+
diff --git a/filter/src/main/cpp/effect/ContrastFilter.hpp b/filter/src/main/cpp/effect/ContrastFilter.hpp
new file mode 100755
index 0000000..1b88e29
--- /dev/null
+++ b/filter/src/main/cpp/effect/ContrastFilter.hpp
@@ -0,0 +1,43 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef ContrastFilter_hpp
+#define ContrastFilter_hpp
+
+#include "../source/macros.h"
+#include "Filter.hpp"
+
+NS_GI_BEGIN
+
+class ContrastFilter : public Filter {
+public:
+ static ContrastFilter* create();
+ bool init();
+ virtual bool proceed(bool bUpdateTargets = true) override;
+
+ void setContrast(float contrast);
+
+protected:
+ ContrastFilter() {};
+
+ float _contrast;
+};
+
+NS_GI_END
+
+#endif /* ContrastFilter_hpp */
diff --git a/filter/src/main/cpp/effect/Convolution3x3Filter.cpp b/filter/src/main/cpp/effect/Convolution3x3Filter.cpp
new file mode 100755
index 0000000..b7bc1ff
--- /dev/null
+++ b/filter/src/main/cpp/effect/Convolution3x3Filter.cpp
@@ -0,0 +1,82 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include "Convolution3x3Filter.hpp"
+
+
+
+NS_GI_BEGIN
+
+
+
+const std::string kConvolution3x3FragmentShaderString = SHADER_STRING
+(
+ precision highp float;
+ uniform sampler2D colorMap;
+ uniform mediump mat3 convolutionMatrix;
+
+ varying vec2 vTexCoord;
+ varying vec2 vLeftTexCoord;
+ varying vec2 vRightTexCoord;
+ varying vec2 vTopTexCoord;
+ varying vec2 vTopLeftTexCoord;
+ varying vec2 vTopRightTexCoord;
+ varying vec2 vBottomTexCoord;
+ varying vec2 vBottomLeftTexCoord;
+ varying vec2 vBottomRightTexCoord;
+
+
+
+ void main()
+ {
+ mediump vec3 bottomColor = texture2D(colorMap, vBottomTexCoord).rgb;
+ mediump vec3 bottomLeftColor = texture2D(colorMap, vBottomLeftTexCoord).rgb;
+ mediump vec3 bottomRightColor = texture2D(colorMap, vBottomRightTexCoord).rgb;
+ mediump vec4 centerColor = texture2D(colorMap, vTexCoord);
+ mediump vec3 leftColor = texture2D(colorMap, vLeftTexCoord).rgb;
+ mediump vec3 rightColor = texture2D(colorMap, vRightTexCoord).rgb;
+ mediump vec3 topColor = texture2D(colorMap, vTopTexCoord).rgb;
+ mediump vec3 topRightColor = texture2D(colorMap, vTopRightTexCoord).rgb;
+ mediump vec3 topLeftColor = texture2D(colorMap, vTopLeftTexCoord).rgb;
+
+ mediump vec3 resultColor = topLeftColor * convolutionMatrix[0][0] + topColor * convolutionMatrix[0][1] + topRightColor * convolutionMatrix[0][2];
+ resultColor += leftColor * convolutionMatrix[1][0] + centerColor.rgb * convolutionMatrix[1][1] + rightColor * convolutionMatrix[1][2];
+ resultColor += bottomLeftColor * convolutionMatrix[2][0] + bottomColor * convolutionMatrix[2][1] + bottomRightColor * convolutionMatrix[2][2];
+
+ gl_FragColor = vec4(resultColor, centerColor.a);
+ }
+ );
+
+
+bool Convolution3x3Filter::init() {
+ if(!NearbySampling3x3Filter::initWithFragmentShaderString(kConvolution3x3FragmentShaderString)) return false;
+
+ _convolutionKernel.set(0.f, 0.f, 0.f,
+ 0.f, 1.f, 0.f,
+ 0.f, 0.f, 0.f);
+
+
+ return true;
+}
+
+bool Convolution3x3Filter::proceed(bool bUpdateTargets/* = true*/) {
+ _filterProgram->setUniformValue("convolutionMatrix", _convolutionKernel);
+ return NearbySampling3x3Filter::proceed(bUpdateTargets);
+}
+
+NS_GI_END
diff --git a/filter/src/main/cpp/effect/Convolution3x3Filter.hpp b/filter/src/main/cpp/effect/Convolution3x3Filter.hpp
new file mode 100755
index 0000000..89d8ff7
--- /dev/null
+++ b/filter/src/main/cpp/effect/Convolution3x3Filter.hpp
@@ -0,0 +1,42 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef Convolution3x3Filter_hpp
+#define Convolution3x3Filter_hpp
+
+#include "../source/macros.h"
+#include "NearbySampling3x3Filter.hpp"
+#include "../source/math.hpp"
+
+NS_GI_BEGIN
+
+class Convolution3x3Filter : public NearbySampling3x3Filter {
+public:
+ virtual bool init();
+ virtual bool proceed(bool bUpdateTargets = true) override;
+protected:
+ Convolution3x3Filter() {};
+
+
+ //The convolution kernel is a 3x3 matrix of values to apply to the pixel and its 8 surrounding pixels.
+ Matrix3 _convolutionKernel;
+};
+
+NS_GI_END
+
+#endif /* Convolution3x3Filter_hpp */
diff --git a/filter/src/main/cpp/effect/CrosshatchFilter.cpp b/filter/src/main/cpp/effect/CrosshatchFilter.cpp
new file mode 100755
index 0000000..03caf16
--- /dev/null
+++ b/filter/src/main/cpp/effect/CrosshatchFilter.cpp
@@ -0,0 +1,114 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include "CrosshatchFilter.hpp"
+
+USING_NS_GI
+
+REGISTER_FILTER_CLASS(CrosshatchFilter)
+
+const std::string kCrosshatchFragmentShaderString = SHADER_STRING
+(
+ uniform sampler2D colorMap;
+ varying highp vec2 vTexCoord;
+ uniform highp float crossHatchSpacing;
+ uniform highp float lineWidth;
+
+ const highp vec3 W = vec3(0.2125, 0.7154, 0.0721);
+
+ void main()
+ {
+ highp float luminance = dot(texture2D(colorMap, vTexCoord).rgb, W);
+
+ lowp vec4 colorToDisplay = vec4(1.0, 1.0, 1.0, 1.0);
+ if (luminance < 1.00)
+ {
+ if (mod(vTexCoord.x + vTexCoord.y, crossHatchSpacing) <= lineWidth)
+ {
+ colorToDisplay = vec4(0.0, 0.0, 0.0, 1.0);
+ }
+ }
+ if (luminance < 0.75)
+ {
+ if (mod(vTexCoord.x - vTexCoord.y, crossHatchSpacing) <= lineWidth)
+ {
+ colorToDisplay = vec4(0.0, 0.0, 0.0, 1.0);
+ }
+ }
+ if (luminance < 0.50)
+ {
+ if (mod(vTexCoord.x + vTexCoord.y - (crossHatchSpacing / 2.0), crossHatchSpacing) <= lineWidth)
+ {
+ colorToDisplay = vec4(0.0, 0.0, 0.0, 1.0);
+ }
+ }
+ if (luminance < 0.3)
+ {
+ if (mod(vTexCoord.x - vTexCoord.y - (crossHatchSpacing / 2.0), crossHatchSpacing) <= lineWidth)
+ {
+ colorToDisplay = vec4(0.0, 0.0, 0.0, 1.0);
+ }
+ }
+
+ gl_FragColor = colorToDisplay;
+ }
+
+);
+
+
+
+
+CrosshatchFilter* CrosshatchFilter::create() {
+ CrosshatchFilter* ret = new (std::nothrow) CrosshatchFilter();
+ if (ret && !ret->init()) {
+ delete ret;
+ ret = 0;
+ }
+ return ret;
+}
+
+bool CrosshatchFilter::init() {
+ if (!initWithFragmentShaderString(kCrosshatchFragmentShaderString)) return false;
+
+
+ setCrossHatchSpacing(0.03);
+ registerProperty("crossHatchSpacing", _crossHatchSpacing, "The fractional width of the image to use as the spacing for the crosshatch. The default is 0.03.", [this](float& crossHatchSpacing){
+ setCrossHatchSpacing(crossHatchSpacing);
+ });
+
+ setLineWidth(0.003);
+ registerProperty("lineWidth", _lineWidth, "A relative width for the crosshatch lines. The default is 0.003.", [this](float& lineWidth){
+ setLineWidth(lineWidth);
+ });
+ return true;
+}
+
+bool CrosshatchFilter::proceed(bool bUpdateTargets/* = true*/) {
+ _filterProgram->setUniformValue("crossHatchSpacing", _crossHatchSpacing);
+ _filterProgram->setUniformValue("lineWidth", _lineWidth);
+ return Filter::proceed(bUpdateTargets);
+}
+
+void CrosshatchFilter::setCrossHatchSpacing(float crossHatchSpacing) {
+ _crossHatchSpacing = crossHatchSpacing;
+}
+
+void CrosshatchFilter::setLineWidth(float lineWidth) {
+ _lineWidth = lineWidth;
+}
+
diff --git a/filter/src/main/cpp/effect/CrosshatchFilter.hpp b/filter/src/main/cpp/effect/CrosshatchFilter.hpp
new file mode 100755
index 0000000..8b7b0a4
--- /dev/null
+++ b/filter/src/main/cpp/effect/CrosshatchFilter.hpp
@@ -0,0 +1,45 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef CrosshatchFilter_hpp
+#define CrosshatchFilter_hpp
+
+#include "../source/macros.h"
+#include "Filter.hpp"
+
+NS_GI_BEGIN
+
+class CrosshatchFilter : public Filter {
+public:
+ static CrosshatchFilter* create();
+ bool init();
+ virtual bool proceed(bool bUpdateTargets = true) override;
+
+ void setCrossHatchSpacing(float crossHatchSpacing);
+ void setLineWidth(float lineWidth);
+
+protected:
+ CrosshatchFilter() {};
+
+ float _crossHatchSpacing;
+ float _lineWidth;
+};
+
+NS_GI_END
+
+#endif /* CrosshatchFilter_hpp */
diff --git a/filter/src/main/cpp/effect/DirectionalNonMaximumSuppressionFilter.cpp b/filter/src/main/cpp/effect/DirectionalNonMaximumSuppressionFilter.cpp
new file mode 100755
index 0000000..485d2c5
--- /dev/null
+++ b/filter/src/main/cpp/effect/DirectionalNonMaximumSuppressionFilter.cpp
@@ -0,0 +1,99 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include "DirectionalNonMaximumSuppressionFilter.hpp"
+
+NS_GI_BEGIN
+
+REGISTER_FILTER_CLASS(DirectionalNonMaximumSuppressionFilter)
+
+const std::string kDirectionalNonmaximumSuppressionFragmentShaderString = SHADER_STRING
+(
+ precision mediump float;
+
+ uniform sampler2D colorMap;
+ uniform highp float texelWidth;
+ uniform highp float texelHeight;
+ uniform mediump float upperThreshold;
+ uniform mediump float lowerThreshold;
+
+ varying highp vec2 vTexCoord;
+
+ void main()
+ {
+ vec3 currentGradientAndDirection = texture2D(colorMap, vTexCoord).rgb;
+ vec2 gradientDirection = ((currentGradientAndDirection.gb * 2.0) - 1.0) * vec2(texelWidth, texelHeight);
+
+ float firstSampledGradientMagnitude = texture2D(colorMap, vTexCoord + gradientDirection).r;
+ float secondSampledGradientMagnitude = texture2D(colorMap, vTexCoord - gradientDirection).r;
+
+ float multiplier = step(firstSampledGradientMagnitude, currentGradientAndDirection.r);
+ multiplier = multiplier * step(secondSampledGradientMagnitude, currentGradientAndDirection.r);
+
+ float thresholdCompliance = smoothstep(lowerThreshold, upperThreshold, currentGradientAndDirection.r);
+ multiplier = multiplier * thresholdCompliance;
+
+ gl_FragColor = vec4(multiplier, multiplier, multiplier, 1.0);
+ }
+ );
+
+
+DirectionalNonMaximumSuppressionFilter* DirectionalNonMaximumSuppressionFilter::create() {
+ DirectionalNonMaximumSuppressionFilter* ret = new (std::nothrow) DirectionalNonMaximumSuppressionFilter();
+ if (ret && !ret->init()) {
+ delete ret;
+ ret = 0;
+ }
+ return ret;
+}
+
+bool DirectionalNonMaximumSuppressionFilter::init() {
+ if (initWithFragmentShaderString(kDirectionalNonmaximumSuppressionFragmentShaderString)) {
+ _texelWidthUniform = _filterProgram->getUniformLocation("texelWidth");
+ _texelHeightUniform = _filterProgram->getUniformLocation("texelWidth");
+
+ _filterProgram->setUniformValue("upperThreshold", (float)0.5);
+ _filterProgram->setUniformValue("lowerThreshold", (float)0.1);
+
+ return true;
+ }
+ return false;
+}
+
+
+bool DirectionalNonMaximumSuppressionFilter::proceed(bool bUpdateTargets/* = true*/) {
+ float texelWidth = 1.0 / _framebuffer->getWidth();
+ float texelHeight = 1.0 / _framebuffer->getHeight();
+
+ Framebuffer* inputFramebuffer = _inputFramebuffers.begin()->second.frameBuffer;
+ RotationMode inputRotation = _inputFramebuffers.begin()->second.rotationMode;
+
+ if (rotationSwapsSize(inputRotation)){
+ texelWidth = 1.0 / _framebuffer->getHeight();
+ texelHeight = 1.0 / _framebuffer->getWidth();
+ }
+
+ _filterProgram->setUniformValue(_texelWidthUniform, texelWidth);
+ _filterProgram->setUniformValue(_texelHeightUniform, texelHeight);
+
+ return Filter::proceed(bUpdateTargets);
+}
+
+
+
+NS_GI_END
diff --git a/filter/src/main/cpp/effect/DirectionalNonMaximumSuppressionFilter.hpp b/filter/src/main/cpp/effect/DirectionalNonMaximumSuppressionFilter.hpp
new file mode 100755
index 0000000..8b1e531
--- /dev/null
+++ b/filter/src/main/cpp/effect/DirectionalNonMaximumSuppressionFilter.hpp
@@ -0,0 +1,44 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef DirectionalNonMaximumSuppressionFilter_hpp
+#define DirectionalNonMaximumSuppressionFilter_hpp
+
+#include "../source/macros.h"
+#include "Filter.hpp"
+
+NS_GI_BEGIN
+
+class DirectionalNonMaximumSuppressionFilter : public Filter {
+public:
+ static DirectionalNonMaximumSuppressionFilter* create();
+ bool init();
+
+ virtual bool proceed(bool bUpdateTargets = true) override;
+
+
+protected:
+ GLuint _texelWidthUniform;
+ GLuint _texelHeightUniform;
+ DirectionalNonMaximumSuppressionFilter() {};
+};
+
+NS_GI_END
+
+
+#endif /* DirectionalNonMaximumSuppressionFilter_hpp */
diff --git a/filter/src/main/cpp/effect/DirectionalSobelEdgeDetectionFilter.cpp b/filter/src/main/cpp/effect/DirectionalSobelEdgeDetectionFilter.cpp
new file mode 100755
index 0000000..c184cc4
--- /dev/null
+++ b/filter/src/main/cpp/effect/DirectionalSobelEdgeDetectionFilter.cpp
@@ -0,0 +1,85 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include "DirectionalSobelEdgeDetectionFilter.hpp"
+
+NS_GI_BEGIN
+
+REGISTER_FILTER_CLASS(DirectionalSobelEdgeDetectionFilter)
+
+const std::string kDirectionalSobelEdgeDetectionFragmentShaderString = SHADER_STRING
+(
+ precision mediump float;
+ uniform sampler2D colorMap;
+
+ varying vec2 vTexCoord;
+ varying vec2 vLeftTexCoord;
+ varying vec2 vRightTexCoord;
+
+ varying vec2 vTopTexCoord;
+ varying vec2 vTopLeftTexCoord;
+ varying vec2 vTopRightTexCoord;
+
+ varying vec2 vBottomTexCoord;
+ varying vec2 vBottomLeftTexCoord;
+ varying vec2 vBottomRightTexCoord;
+
+
+ void main()
+ {
+ float bottomLeftIntensity = texture2D(colorMap, vBottomLeftTexCoord).r;
+ float topRightIntensity = texture2D(colorMap, vTopRightTexCoord).r;
+ float topLeftIntensity = texture2D(colorMap, vTopLeftTexCoord).r;
+ float bottomRightIntensity = texture2D(colorMap, vBottomRightTexCoord).r;
+ float leftIntensity = texture2D(colorMap, vLeftTexCoord).r;
+ float rightIntensity = texture2D(colorMap, vRightTexCoord).r;
+ float bottomIntensity = texture2D(colorMap, vBottomTexCoord).r;
+ float topIntensity = texture2D(colorMap, vTopTexCoord).r;
+
+ vec2 gradientDirection;
+ gradientDirection.x = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomRightIntensity + 2.0 * rightIntensity + topRightIntensity;
+ gradientDirection.y = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + bottomLeftIntensity + 2.0 * bottomIntensity + bottomRightIntensity;
+
+ float gradientMagnitude = length(gradientDirection);
+ vec2 normalizedDirection = normalize(gradientDirection);
+ normalizedDirection = sign(normalizedDirection) * floor(abs(normalizedDirection) + 0.617316); // Offset by 1-sin(pi/8) to set to 0 if near axis, 1 if away
+ normalizedDirection = (normalizedDirection + 1.0) * 0.5; // Place -1.0 - 1.0 within 0 - 1.0
+
+ gl_FragColor = vec4(gradientMagnitude, normalizedDirection.x, normalizedDirection.y, 1.0);
+ }
+ );
+
+
+DirectionalSobelEdgeDetectionFilter* DirectionalSobelEdgeDetectionFilter::create() {
+ DirectionalSobelEdgeDetectionFilter* ret = new (std::nothrow) DirectionalSobelEdgeDetectionFilter();
+ if (ret && !ret->init()) {
+ delete ret;
+ ret = 0;
+ }
+ return ret;
+}
+
+bool DirectionalSobelEdgeDetectionFilter::init() {
+ if (initWithFragmentShaderString(kDirectionalSobelEdgeDetectionFragmentShaderString)) {
+ return true;
+ }
+ return false;
+}
+
+
+NS_GI_END
diff --git a/filter/src/main/cpp/effect/DirectionalSobelEdgeDetectionFilter.hpp b/filter/src/main/cpp/effect/DirectionalSobelEdgeDetectionFilter.hpp
new file mode 100755
index 0000000..d245ac4
--- /dev/null
+++ b/filter/src/main/cpp/effect/DirectionalSobelEdgeDetectionFilter.hpp
@@ -0,0 +1,40 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef DirectionalSobelEdgeDetectionFilter_hpp
+#define DirectionalSobelEdgeDetectionFilter_hpp
+
+#include "../source/macros.h"
+#include "NearbySampling3x3Filter.hpp"
+
+NS_GI_BEGIN
+
+class DirectionalSobelEdgeDetectionFilter : public NearbySampling3x3Filter {
+public:
+ static DirectionalSobelEdgeDetectionFilter* create();
+ bool init();
+
+
+protected:
+
+ DirectionalSobelEdgeDetectionFilter() {};
+};
+
+NS_GI_END
+
+#endif /* DirectionalSobelEdgeDetectionFilter_hpp */
diff --git a/filter/src/main/cpp/effect/EmbossFilter.cpp b/filter/src/main/cpp/effect/EmbossFilter.cpp
new file mode 100755
index 0000000..7d3ee8e
--- /dev/null
+++ b/filter/src/main/cpp/effect/EmbossFilter.cpp
@@ -0,0 +1,58 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include "EmbossFilter.hpp"
+
+USING_NS_GI
+
+REGISTER_FILTER_CLASS(EmbossFilter)
+
+EmbossFilter* EmbossFilter::create() {
+ EmbossFilter* ret = new (std::nothrow) EmbossFilter();
+ if (ret && !ret->init()) {
+ delete ret;
+ ret = 0;
+ }
+ return ret;
+}
+
+bool EmbossFilter::init() {
+ if (!Convolution3x3Filter::init()) return false;
+
+ _intensity = 1.0;
+ setIntensity(_intensity);
+
+ registerProperty("intensity", _intensity, "The strength of the embossing, from 0.0 to 4.0, with 1.0 as the normal level", [this](float& intensity){
+ setIntensity(intensity);
+ });
+
+ return true;
+}
+
+void EmbossFilter::setIntensity(float intensity) {
+ _intensity = intensity;
+ if (_intensity > 4.0) _intensity = 4.0;
+ else if (_intensity < 0.0) _intensity = 0.0;
+
+ _convolutionKernel.set(-2.0 * _intensity, -_intensity, 0.0,
+ -_intensity, 1.0, _intensity,
+ 0.0, _intensity, _intensity * 2.0
+ );
+}
+
+
diff --git a/filter/src/main/cpp/effect/EmbossFilter.hpp b/filter/src/main/cpp/effect/EmbossFilter.hpp
new file mode 100755
index 0000000..c9623a7
--- /dev/null
+++ b/filter/src/main/cpp/effect/EmbossFilter.hpp
@@ -0,0 +1,42 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef EmbossFilter_hpp
+#define EmbossFilter_hpp
+
+#include "../source/macros.h"
+#include "Convolution3x3Filter.hpp"
+
+NS_GI_BEGIN
+
+class EmbossFilter : public Convolution3x3Filter {
+public:
+ static EmbossFilter* create();
+ bool init();
+
+ void setIntensity(float intensity);
+
+protected:
+ EmbossFilter() {};
+
+ float _intensity;
+};
+
+NS_GI_END
+
+#endif /* EmbossFilter_hpp */
diff --git a/filter/src/main/cpp/effect/ExposureFilter.cpp b/filter/src/main/cpp/effect/ExposureFilter.cpp
new file mode 100755
index 0000000..58c7cc9
--- /dev/null
+++ b/filter/src/main/cpp/effect/ExposureFilter.cpp
@@ -0,0 +1,69 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include "ExposureFilter.hpp"
+
+USING_NS_GI
+
+REGISTER_FILTER_CLASS(ExposureFilter)
+
+const std::string kExposureFragmentShaderString = SHADER_STRING
+(
+ uniform sampler2D colorMap;
+ uniform lowp float exposure;
+ varying highp vec2 vTexCoord;
+
+ void main()
+ {
+ lowp vec4 color = texture2D(colorMap, vTexCoord);
+ gl_FragColor = vec4(color.rgb * pow(2.0, exposure), color.a);
+ }
+);
+
+
+ExposureFilter* ExposureFilter::create() {
+ ExposureFilter* ret = new (std::nothrow) ExposureFilter();
+ if (ret && !ret->init()) {
+ delete ret;
+ ret = 0;
+ }
+ return ret;
+}
+
+bool ExposureFilter::init() {
+ if (!initWithFragmentShaderString(kExposureFragmentShaderString)) return false;
+
+ _exposure = 0.0;
+ registerProperty("exposure", _exposure, "The exposure of the image. Exposure ranges from -10.0 to 10.0 (max contrast), with 0.0 as the normal level", [this](float& exposure){
+ setExposure(exposure);
+ });
+
+ return true;
+}
+
+void ExposureFilter::setExposure(float exposure) {
+ _exposure = exposure;
+ if (_exposure > 10.0) _exposure = 10.0;
+ else if (_exposure < -10.0) _exposure = -10.0;
+}
+
+bool ExposureFilter::proceed(bool bUpdateTargets/* = true*/) {
+ _filterProgram->setUniformValue("exposure", _exposure);
+ return Filter::proceed(bUpdateTargets);
+}
+
diff --git a/filter/src/main/cpp/effect/ExposureFilter.hpp b/filter/src/main/cpp/effect/ExposureFilter.hpp
new file mode 100755
index 0000000..68444a0
--- /dev/null
+++ b/filter/src/main/cpp/effect/ExposureFilter.hpp
@@ -0,0 +1,43 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef ExposureFilter_hpp
+#define ExposureFilter_hpp
+
+#include "../source/macros.h"
+#include "Filter.hpp"
+
+NS_GI_BEGIN
+
+class ExposureFilter : public Filter {
+public:
+ static ExposureFilter* create();
+ bool init();
+ virtual bool proceed(bool bUpdateTargets = true) override;
+
+ void setExposure(float exposure);
+
+protected:
+ ExposureFilter() {};
+
+ float _exposure;
+};
+
+NS_GI_END
+
+#endif /* BrightnessFilter_hpp */
diff --git a/filter/src/main/cpp/effect/Filter.cpp b/filter/src/main/cpp/effect/Filter.cpp
new file mode 100755
index 0000000..ed0ce98
--- /dev/null
+++ b/filter/src/main/cpp/effect/Filter.cpp
@@ -0,0 +1,424 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include "Filter.hpp"
+#include "../source/Context.hpp"
+
+
+NS_GI_BEGIN
+
+std::map> Filter::_filterFactories ;
+
+Filter::Filter()
+:_filterProgram(0)
+,_filterClassName("")
+{
+ _backgroundColor.r = 0.0;
+ _backgroundColor.g = 0.0;
+ _backgroundColor.b = 0.0;
+ _backgroundColor.a = 1.0;
+}
+
+Filter::~Filter() {
+ if (_filterProgram) {
+ delete _filterProgram;
+ _filterProgram = 0;
+ }
+}
+
+Filter* Filter::create(const std::string& filterClassName) {
+ std::map>::iterator it = _filterFactories.find(filterClassName);
+ if (it == _filterFactories.end())
+ return 0;
+ else {
+ Filter* filter = it->second();
+ filter->setFilterClassName(filterClassName);
+ return it->second();
+ }
+}
+
+Filter* Filter::createWithShaderString(const std::string& vertexShaderSource, const std::string& fragmentShaderSource) {
+ Filter* filter = new Filter();
+ if (!filter->initWithShaderString(vertexShaderSource, fragmentShaderSource)) {
+ delete filter;
+ filter = 0;
+ return 0;
+ }
+ return filter;
+}
+
+Filter* Filter::createWithFragmentShaderString(const std::string& fragmentShaderSource) {
+ Filter* filter = new Filter();
+ if (!filter->initWithFragmentShaderString(fragmentShaderSource)) {
+ delete filter;
+ filter = 0;
+ return 0;
+ }
+ return filter;
+}
+
+bool Filter::initWithShaderString(const std::string& vertexShaderSource, const std::string& fragmentShaderSource) {
+
+ _filterProgram = GLProgram::createByShaderString(vertexShaderSource, fragmentShaderSource);
+ _filterPositionAttribute = _filterProgram->getAttribLocation("position");
+ //_filterTexCoordAttribute = _filterProgram->getAttribLocation("texCoord");
+ Context::getInstance()->setActiveShaderProgram(_filterProgram);
+ CHECK_GL(glEnableVertexAttribArray(_filterPositionAttribute));
+ //glEnableVertexAttribArray(_filterTexCoordAttribute);
+
+ return true;
+}
+
+bool Filter::initWithFragmentShaderString(const std::string& fragmentShaderSource, int inputNumber/* = 1*/) {
+ _inputNum = inputNumber;
+ return initWithShaderString(_getVertexShaderString(), fragmentShaderSource);
+}
+
+std::string Filter::_getVertexShaderString() const {
+
+ if (_inputNum <= 1)
+ {
+ return kDefaultVertexShader;
+ }
+
+ std::string shaderStr = "\
+ attribute vec4 position;\n\
+ attribute vec4 texCoord;\n\
+ varying vec2 vTexCoord;\n\
+ ";
+ for (int i = 1; i < _inputNum; ++i) {
+ shaderStr += str_format("\
+ attribute vec4 texCoord%d;\n\
+ varying vec2 vTexCoord%d;\n\
+ ", i, i);
+ }
+ shaderStr += "\
+ void main()\n\
+ {\n\
+ gl_Position = position;\n\
+ vTexCoord = texCoord.xy;\n\
+ ";
+ for (int i = 1; i < _inputNum; ++i) {
+ shaderStr += str_format("vTexCoord%d = texCoord%d.xy;\n", i, i);
+ }
+ shaderStr += "}\n";
+
+ return shaderStr;
+}
+
+bool Filter::proceed(bool bUpdateTargets/* = true*/) {
+ static const GLfloat imageVertices[] = {
+ -1.0f, -1.0f,
+ 1.0f, -1.0f,
+ -1.0f, 1.0f,
+ 1.0f, 1.0f,
+ };
+
+ Context::getInstance()->setActiveShaderProgram(_filterProgram);
+ _framebuffer->active();
+ CHECK_GL(glClearColor(_backgroundColor.r, _backgroundColor.g, _backgroundColor.b, _backgroundColor.a));
+ CHECK_GL(glClear(GL_COLOR_BUFFER_BIT));
+ for (std::map::const_iterator it = _inputFramebuffers.begin(); it != _inputFramebuffers.end(); ++it) {
+ int texIdx = it->first;
+ Framebuffer* fb = it->second.frameBuffer;
+ CHECK_GL(glActiveTexture(GL_TEXTURE0 + texIdx));
+ CHECK_GL(glBindTexture(GL_TEXTURE_2D, fb->getTexture()));
+ _filterProgram->setUniformValue(
+ texIdx == 0 ? "colorMap" : str_format("colorMap%d", texIdx),
+ texIdx);
+ // texcoord attribute
+ GLuint filterTexCoordAttribute = _filterProgram->getAttribLocation(texIdx == 0 ? "texCoord" : str_format("texCoord%d", texIdx));
+ CHECK_GL(glEnableVertexAttribArray(filterTexCoordAttribute));
+ CHECK_GL(glVertexAttribPointer(filterTexCoordAttribute, 2, GL_FLOAT, 0, 0, _getTexureCoordinate(it->second.rotationMode)));
+ }
+ CHECK_GL(glVertexAttribPointer(_filterPositionAttribute, 2, GL_FLOAT, 0, 0, imageVertices));
+ CHECK_GL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
+
+ _framebuffer->inactive();
+
+ return Source::proceed(bUpdateTargets);
+}
+
+const GLfloat* Filter::_getTexureCoordinate(const RotationMode& rotationMode) const {
+ static const GLfloat noRotationTextureCoordinates[] = {
+ 0.0f, 0.0f,
+ 1.0f, 0.0f,
+ 0.0f, 1.0f,
+ 1.0f, 1.0f,
+ };
+
+ static const GLfloat rotateLeftTextureCoordinates[] = {
+ 1.0f, 0.0f,
+ 1.0f, 1.0f,
+ 0.0f, 0.0f,
+ 0.0f, 1.0f,
+ };
+
+ static const GLfloat rotateRightTextureCoordinates[] = {
+ 0.0f, 1.0f,
+ 0.0f, 0.0f,
+ 1.0f, 1.0f,
+ 1.0f, 0.0f,
+ };
+
+ static const GLfloat verticalFlipTextureCoordinates[] = {
+ 0.0f, 1.0f,
+ 1.0f, 1.0f,
+ 0.0f, 0.0f,
+ 1.0f, 0.0f,
+ };
+
+ static const GLfloat horizontalFlipTextureCoordinates[] = {
+ 1.0f, 0.0f,
+ 0.0f, 0.0f,
+ 1.0f, 1.0f,
+ 0.0f, 1.0f,
+ };
+
+ static const GLfloat rotateRightVerticalFlipTextureCoordinates[] = {
+ 0.0f, 0.0f,
+ 0.0f, 1.0f,
+ 1.0f, 0.0f,
+ 1.0f, 1.0f,
+ };
+
+ static const GLfloat rotateRightHorizontalFlipTextureCoordinates[] = {
+ 1.0f, 1.0f,
+ 1.0f, 0.0f,
+ 0.0f, 1.0f,
+ 0.0f, 0.0f,
+ };
+
+ static const GLfloat rotate180TextureCoordinates[] = {
+ 1.0f, 1.0f,
+ 0.0f, 1.0f,
+ 1.0f, 0.0f,
+ 0.0f, 0.0f,
+ };
+
+ switch (rotationMode) {
+ case NoRotation:
+ return noRotationTextureCoordinates;
+ break;
+ case RotateLeft:
+ return rotateLeftTextureCoordinates;
+ break;
+ case RotateRight:
+ return rotateRightTextureCoordinates;
+ break;
+ case FlipVertical:
+ return verticalFlipTextureCoordinates;
+ break;
+ case FlipHorizontal:
+ return horizontalFlipTextureCoordinates;
+ break;
+ case RotateRightFlipVertical:
+ return rotateRightVerticalFlipTextureCoordinates;
+ break;
+ case RotateRightFlipHorizontal:
+ return rotateRightHorizontalFlipTextureCoordinates;
+ break;
+ case Rotate180:
+ return rotate180TextureCoordinates;
+ break;
+ default:
+ break;
+ }
+}
+
+void Filter::update(float frameTime) {
+ if (_inputFramebuffers.empty()) return;
+
+ if (Context::getInstance()->isCapturingFrame && this == Context::getInstance()->captureUpToFilter) {
+ int captureWidth = Context::getInstance()->captureWidth;
+ int captureHeight = Context::getInstance()->captureHeight;
+
+ _framebuffer = Context::getInstance()->getFramebufferCache()->fetchFramebuffer(captureWidth, captureHeight);
+ proceed(false);
+
+ _framebuffer->active();
+ Context::getInstance()->capturedFrameData = new unsigned char[captureWidth * captureHeight * 4];
+ CHECK_GL(glReadPixels(0, 0, captureWidth, captureHeight, GL_RGBA, GL_UNSIGNED_BYTE, Context::getInstance()->capturedFrameData));
+ _framebuffer->inactive();
+ } else {
+ // todo
+ Framebuffer* firstInputFramebuffer = _inputFramebuffers.begin()->second.frameBuffer;
+ RotationMode firstInputRotation = _inputFramebuffers.begin()->second.rotationMode;
+ if (!firstInputFramebuffer) return;
+
+ int rotatedFramebufferWidth = firstInputFramebuffer->getWidth();
+ int rotatedFramebufferHeight = firstInputFramebuffer->getHeight();
+ if (rotationSwapsSize(firstInputRotation))
+ {
+ rotatedFramebufferWidth = firstInputFramebuffer->getHeight();
+ rotatedFramebufferHeight = firstInputFramebuffer->getWidth();
+ }
+
+ if (_framebufferScale != 1.0) {
+ rotatedFramebufferWidth = int(rotatedFramebufferWidth * _framebufferScale);
+ rotatedFramebufferHeight = int(rotatedFramebufferHeight * _framebufferScale);
+ }
+
+ _framebuffer = Context::getInstance()->getFramebufferCache()->fetchFramebuffer(rotatedFramebufferWidth, rotatedFramebufferHeight);
+ proceed();
+ }
+
+ _framebuffer->release();
+ _framebuffer = 0;
+}
+
+bool Filter::registerProperty(const std::string& name, int defaultValue, const std::string& comment/* = ""*/, std::function setCallback/* = 0*/) {
+ if (hasProperty(name)) return false;
+ IntProperty property;
+ property.type = "int";
+ property.value = defaultValue;
+ property.comment = comment;
+ property.setCallback = setCallback;
+ _intProperties[name] = property;
+ return true;
+}
+
+bool Filter::registerProperty(const std::string& name, float defaultValue, const std::string& comment/* = ""*/, std::function setCallback/* = 0*/) {
+ if (hasProperty(name)) return false;
+ FloatProperty property;
+ property.type = "float";
+ property.value = defaultValue;
+ property.comment = comment;
+ property.setCallback = setCallback;
+ _floatProperties[name] = property;
+ return true;
+}
+
+bool Filter::registerProperty(const std::string& name, const std::string& defaultValue, const std::string& comment/* = ""*/, std::function setCallback/* = 0*/) {
+ if (hasProperty(name)) return false;
+ StringProperty property;
+ property.type = "string";
+ property.value = defaultValue;
+ property.comment = comment;
+ property.setCallback = setCallback;
+ _stringProperties[name] = property;
+ return true;
+}
+
+bool Filter::setProperty(const std::string& name, int value) {
+ Property* rawProperty = _getProperty(name);
+ if (!rawProperty) {
+ Log("WARNING", "Filter::setProperty invalid property %s", name.c_str());
+ return false;
+ } else if (rawProperty->type != "int") {
+ Log("WARNING", "Filter::setProperty The property type is expected to be %s", rawProperty->type.c_str());
+ return false;
+ }
+ IntProperty* property = ((IntProperty*)rawProperty);
+ property->value = value;
+ if (property->setCallback)
+ property->setCallback(value);
+ return true;
+}
+
+bool Filter::setProperty(const std::string& name, float value) {
+ Property* rawProperty = _getProperty(name);
+ if (!rawProperty) {
+ Log("WARNING", "Filter::setProperty invalid property %s", name.c_str());
+ return false;
+ } else if (rawProperty->type != "float") {
+ Log("WARNING", "Filter::setProperty The property type is expected to be %s", rawProperty->type.c_str());
+ return false;
+ }
+ FloatProperty* property = ((FloatProperty*)rawProperty);
+ if (property->setCallback)
+ property->setCallback(value);
+ property->value = value;
+
+ return true;
+}
+
+bool Filter::setProperty(const std::string& name, std::string value) {
+ Property* rawProperty = _getProperty(name);
+ if (!rawProperty) {
+ Log("WARNING", "Filter::setProperty invalid property %s", name.c_str());
+ return false;
+ } else if (rawProperty->type != "string") {
+ Log("WARNING", "Filter::setProperty The property type is expected to be %s", rawProperty->type.c_str());
+ return false;
+ }
+ StringProperty* property = ((StringProperty*)rawProperty);
+ property->value = value;
+ if (property->setCallback)
+ property->setCallback(value);
+ return true;
+}
+
+bool Filter::getProperty(const std::string& name, int& retValue) {
+ Property* property = _getProperty(name);
+ if (!property) return false;
+ retValue = ((IntProperty*)property)->value;
+ return true;
+}
+
+bool Filter::getProperty(const std::string& name, float& retValue) {
+ Property* property = _getProperty(name);
+ if (!property) return false;
+ retValue = ((FloatProperty*)property)->value;
+ return true;
+}
+
+bool Filter::getProperty(const std::string& name, std::string& retValue) {
+ Property* property = _getProperty(name);
+ if (!property) return false;
+ retValue = ((StringProperty*)property)->value;
+ return true;
+}
+
+Filter::Property* Filter::_getProperty(const std::string& name) {
+ if (_intProperties.find(name) != _intProperties.end()) {
+ return &_intProperties[name];
+ }
+ if (_floatProperties.find(name) != _floatProperties.end()) {
+ return &_floatProperties[name];
+ }
+ if (_stringProperties.find(name) != _stringProperties.end()) {
+ return &_stringProperties[name];
+ }
+ return 0;
+}
+
+bool Filter::hasProperty(const std::string& name, const std::string type) {
+ Property* property = _getProperty(name);
+ return property && property->type == type ? true : false;
+}
+
+bool Filter::hasProperty(const std::string& name) {
+ return _getProperty(name) ? true : false;
+}
+
+bool Filter::getPropertyComment(const std::string& name, std::string& retComment) {
+ Property* property = _getProperty(name);
+ if (!property) return false;
+ retComment = std::string("[") + property->type + "] " + property->comment;
+ return true;
+}
+
+bool Filter::getPropertyType(const std::string& name, std::string& retType) {
+ Property* property = _getProperty(name);
+ if (!property) return false;
+ retType = property->type;
+ return true;
+}
+
+NS_GI_END
diff --git a/filter/src/main/cpp/effect/Filter.hpp b/filter/src/main/cpp/effect/Filter.hpp
new file mode 100755
index 0000000..76302ce
--- /dev/null
+++ b/filter/src/main/cpp/effect/Filter.hpp
@@ -0,0 +1,162 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef Filter_hpp
+#define Filter_hpp
+
+#include "../source/macros.h"
+#include "string"
+#include "../source/Source.hpp"
+#include "../source/Target.hpp"
+#include "../source/GLProgram.hpp"
+#include "../source/Ref.hpp"
+#include "../source/util.h"
+
+NS_GI_BEGIN
+
+
+// Hardcode the vertex shader for standard filters, but this can be overridden
+ const std::string kDefaultVertexShader = SHADER_STRING
+ (
+ attribute vec4 position;
+ attribute vec4 texCoord;
+
+ varying vec2 vTexCoord;
+
+ void main()
+ {
+ gl_Position = position;
+ vTexCoord = texCoord.xy;
+ }
+ );
+
+ const std::string kDefaultFragmentShader = SHADER_STRING
+ (
+ varying highp vec2 vTexCoord;
+ uniform sampler2D colorMap;
+
+ void main()
+ {
+ gl_FragColor = texture2D(colorMap, vTexCoord);
+ }
+ );
+
+ class Filter : public Source, public Target {
+ public:
+ virtual ~Filter();
+
+ static Filter* create(const std::string& filterClassName);
+ static Filter* createWithShaderString(const std::string& vertexShaderSource, const std::string& fragmentShaderSource);
+ static Filter* createWithFragmentShaderString(const std::string& fragmentShaderSource);
+
+ bool initWithShaderString(const std::string& vertexShaderSource, const std::string& fragmentShaderSource);
+ virtual bool initWithFragmentShaderString(const std::string& fragmentShaderSource, int inputNumber = 1);
+ void setFilterClassName(const std::string filterClassName) {_filterClassName = filterClassName; }
+ std::string getFilterClassName() const { return _filterClassName; };
+
+ virtual void update(float frameTime) override;
+ virtual bool proceed(bool bUpdateTargets = true) override;
+ GLProgram* getProgram() const { return _filterProgram; };
+
+ // property setters & getters
+ bool registerProperty(const std::string& name, int defaultValue, const std::string& comment = "", std::function setCallback = 0);
+ bool registerProperty(const std::string& name, float defaultValue, const std::string& comment = "", std::function setCallback = 0);
+ bool registerProperty(const std::string& name, const std::string& defaultValue, const std::string& comment = "", std::function setCallback = 0);
+ bool setProperty(const std::string& name, int value);
+ bool setProperty(const std::string& name, float value);
+ bool setProperty(const std::string& name, std::string value);
+ bool getProperty(const std::string& name, int& retValue);
+ bool getProperty(const std::string& name, float& retValue);
+ bool getProperty(const std::string& name, std::string& retValue);
+ bool hasProperty(const std::string& name);
+ bool hasProperty(const std::string& name, const std::string type);
+ bool getPropertyComment(const std::string& name, std::string& retComment);
+ bool getPropertyType(const std::string& name, std::string& retType);
+
+#if PLATFORM == PLATFORM_ANDROID
+ class Registry {
+ public:
+ Registry(const std::string& name, std::function createFunc) {
+ Filter::_registerFilterClass(name, createFunc);
+ }
+ };
+ static void _registerFilterClass(const std::string& filterClassName, std::function createFunc) {
+ //Log("jin", "Filter::registerClass : %s", filterClassName.c_str());
+ _filterFactories[filterClassName] = createFunc;
+ }
+#endif
+
+ protected:
+ GLProgram* _filterProgram;
+ GLuint _filterPositionAttribute;
+ std::string _filterClassName;
+ struct {
+ float r; float g; float b; float a;
+ } _backgroundColor;
+
+ Filter();
+ std::string _getVertexShaderString() const;
+ const GLfloat* _getTexureCoordinate(const RotationMode& rotationMode) const;
+
+ // properties
+ struct Property {
+ std::string type;
+ std::string comment;
+ };
+ Property* _getProperty(const std::string& name);
+
+ struct IntProperty : Property{
+ int value;
+ std::function setCallback;
+ };
+ std::map _intProperties;
+
+ struct FloatProperty : Property {
+ float value;
+ std::function setCallback;
+ };
+ std::map _floatProperties;
+
+ struct StringProperty : Property {
+ std::string value;
+ std::function setCallback;
+ };
+ std::map _stringProperties;
+
+ private:
+ static std::map> _filterFactories;
+ };
+
+#if PLATFORM == PLATFORM_ANDROID
+#define REGISTER_FILTER_CLASS(className) \
+class className##Registry { \
+ public: \
+ static Filter* newInstance() { \
+ return className::create(); \
+ } \
+ private: \
+ static const Filter::Registry _registry; \
+}; \
+const Filter::Registry className##Registry::_registry(#className, className##Registry::newInstance);
+#elif PLATFORM == PLATFORM_IOS
+#define REGISTER_FILTER_CLASS(className)
+#endif
+
+NS_GI_END
+
+#endif /* Filter_hpp */
diff --git a/filter/src/main/cpp/effect/FilterGroup.cpp b/filter/src/main/cpp/effect/FilterGroup.cpp
new file mode 100755
index 0000000..e24a9c2
--- /dev/null
+++ b/filter/src/main/cpp/effect/FilterGroup.cpp
@@ -0,0 +1,219 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include
+#include "FilterGroup.hpp"
+#include
+#include "../source/Context.hpp"
+
+NS_GI_BEGIN
+
+REGISTER_FILTER_CLASS(FilterGroup)
+
+FilterGroup::FilterGroup()
+:_terminalFilter(0)
+{
+}
+
+FilterGroup::~FilterGroup() {
+ removeAllFilters();
+ _terminalFilter = 0;
+}
+
+FilterGroup* FilterGroup::create() {
+ FilterGroup* ret = new (std::nothrow) FilterGroup();
+ if (ret && ret->init()) {
+ //ret->autorelease();
+ } else {
+ delete ret;
+ ret = 0;
+ }
+ return ret;
+}
+
+FilterGroup* FilterGroup::create(std::vector filters) {
+ FilterGroup* ret = new (std::nothrow) FilterGroup();
+ if (ret && ret->init(filters)) {
+ //ret->autorelease();
+ } else {
+ delete ret;
+ ret = 0;
+ }
+ return ret;
+}
+
+bool FilterGroup::init() {
+ return true;
+}
+
+
+bool FilterGroup::init(std::vector filters) {
+ if (0 == filters.size()) return true;
+ _filters = filters;
+
+ for (auto const& filter : filters ) {
+ Ref* ref = dynamic_cast[(filter);
+ if (ref) {
+ ref->retain();
+ }
+ }
+
+ setTerminalFilter(_predictTerminalFilter(filters[filters.size() - 1]));
+ return true;
+}
+
+bool FilterGroup::hasFilter(const Filter* filter) const {
+ auto it = std::find(_filters.begin(), _filters.end(), filter);
+ return it != _filters.end();
+}
+
+void FilterGroup::addFilter(Filter* filter) {
+ if (hasFilter(filter)) return;
+
+ _filters.push_back(filter);
+
+ Ref* ref = dynamic_cast][(filter);
+ if (ref) {
+ ref->retain();
+ }
+
+ setTerminalFilter(_predictTerminalFilter(filter));
+}
+
+void FilterGroup::removeFilter(Filter* filter) {
+ auto itr = std::find(_filters.begin(), _filters.end(), filter);
+ if (itr != _filters.end()) {
+ Ref* ref = dynamic_cast][(*itr);
+ if (ref) {
+ ref->release();
+ }
+ _filters.erase(itr);
+ }
+}
+
+void FilterGroup::removeAllFilters() {
+ for (auto const& filter : _filters ) {
+ Ref* ref = dynamic_cast][(filter);
+ if (ref) {
+ ref->release();
+ }
+ }
+ _filters.clear();
+}
+
+Filter* FilterGroup::_predictTerminalFilter(Filter* filter) {
+ if (filter->getTargets().size() == 0)
+ return filter;
+ else
+ return _predictTerminalFilter(dynamic_cast(filter->getTargets().begin()->first));
+}
+
+Source* FilterGroup::addTarget(Target* target) {
+ if (_terminalFilter)
+ return _terminalFilter->addTarget(target);
+ else
+ return 0;
+}
+
+//#if GI_TARGET_PLATFORM == GI_PLATFORM_IOS
+//Source* FilterGroup::addTarget(id target) {
+// if (_terminalFilter)
+// return _terminalFilter->addTarget(target);
+// else
+// return 0;
+//}
+//#endif
+
+void FilterGroup::removeTarget(Target* target) {
+ if (_terminalFilter)
+ _terminalFilter->removeTarget(target);
+}
+
+void FilterGroup::removeAllTargets() {
+ if (_terminalFilter)
+ _terminalFilter->removeAllTargets();
+}
+
+bool FilterGroup::hasTarget(const Target* target) const {
+ if (_terminalFilter)
+ return _terminalFilter->hasTarget(target);
+ else
+ return false;
+}
+
+std::map& FilterGroup::getTargets() {
+ assert(_terminalFilter);
+ return _terminalFilter->getTargets();
+}
+
+bool FilterGroup::proceed(bool bUpdateTargets/* = true*/) {
+
+ return true;
+}
+
+void FilterGroup::update(float frameTime) {
+ proceed();
+ if (Context::getInstance()->isCapturingFrame && this == Context::getInstance()->captureUpToFilter) {
+ Context::getInstance()->captureUpToFilter = _terminalFilter;
+ }
+
+ for(auto& filter : _filters){
+ if (filter->isPrepared()) {
+ filter->update(frameTime);
+ filter->unPrepare();
+ }
+ }
+}
+
+void FilterGroup::updateTargets(float frameTime) {
+ if (_terminalFilter)
+ _terminalFilter->updateTargets(frameTime);
+}
+
+void FilterGroup::setFramebuffer(Framebuffer* fb, RotationMode outputRotation/* = RotationMode::NoRotation*/) {
+ //if (_terminalFilter)
+ // _terminalFilter->setFramebuffer(fb);
+}
+
+Framebuffer* FilterGroup::getFramebuffer() const {
+ //if (_terminalFilter)
+ // return _terminalFilter->getFramebuffer();
+ return 0;
+}
+
+void FilterGroup::setInputFramebuffer(Framebuffer* framebuffer, RotationMode rotationMode/* = NoRotation*/, int texIdx/* = 0*/) {
+ for (auto& filter : _filters) {
+ filter->setInputFramebuffer(framebuffer, rotationMode, texIdx);
+ }
+}
+
+bool FilterGroup::isPrepared() const {
+// for (auto& filter : _filters) {
+// if (!filter->isPrepared())
+// return false;
+// }
+ return true;
+}
+
+void FilterGroup::unPrepare() {
+ //for (auto& filter : _filters) {
+ // filter->unPrepeared();
+ //}
+}
+
+NS_GI_END
diff --git a/filter/src/main/cpp/effect/FilterGroup.hpp b/filter/src/main/cpp/effect/FilterGroup.hpp
new file mode 100755
index 0000000..3582f07
--- /dev/null
+++ b/filter/src/main/cpp/effect/FilterGroup.hpp
@@ -0,0 +1,77 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef FilterGroup_hpp
+#define FilterGroup_hpp
+
+#include "../source/macros.h"
+#include "../source/Source.hpp"
+#include "../source/Target.hpp"
+#include
+#include "Filter.hpp"
+
+NS_GI_BEGIN
+
+class FilterGroup : public Filter {
+public:
+ virtual ~FilterGroup();
+
+ static FilterGroup* create();
+ static FilterGroup* create(std::vector filters);
+
+ bool init();
+ bool init(std::vector filters);
+ bool hasFilter(const Filter* filter) const;
+ void addFilter(Filter* filter);
+ void removeFilter(Filter* filter);
+ void removeAllFilters();
+
+ // Manually specify the terminal filter, which is the final output filter of sequence
+ // Most often, it's not necessary to specify the terminal filter manually,
+ // as the terminal filter will be specified automatically.
+ void setTerminalFilter(Filter* filter) { _terminalFilter = filter; }
+
+ virtual Source* addTarget(Target* target) override;
+//#if GI_TARGET_PLATFORM == GI_PLATFORM_IOS
+// virtual Source* addTarget(id target) override;
+//#endif
+ virtual void removeTarget(Target* target) override;
+ virtual void removeAllTargets() override;
+ virtual bool hasTarget(const Target* target) const override;
+ virtual std::map& getTargets() override;
+ virtual bool proceed(bool bUpdateTargets = true) override;
+ virtual void update(float frameTime) override;
+ virtual void updateTargets(float frameTime) override;
+ virtual void setFramebuffer(Framebuffer* fb, RotationMode outputRotation = RotationMode::NoRotation) override;
+ virtual Framebuffer* getFramebuffer() const override;
+ virtual void setInputFramebuffer(Framebuffer* framebuffer, RotationMode rotationMode = NoRotation, int texIdx = 0) override;
+ virtual bool isPrepared() const override;
+ virtual void unPrepare() override;
+
+protected:
+ std::vector _filters;
+ Filter* _terminalFilter;
+
+ FilterGroup();
+ static Filter* _predictTerminalFilter(Filter* filter);
+
+};
+
+NS_GI_END
+
+#endif /* FilterGroup_hpp */
diff --git a/filter/src/main/cpp/effect/GaussianBlurFilter.cpp b/filter/src/main/cpp/effect/GaussianBlurFilter.cpp
new file mode 100755
index 0000000..ce65c11
--- /dev/null
+++ b/filter/src/main/cpp/effect/GaussianBlurFilter.cpp
@@ -0,0 +1,86 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include
+#include "GaussianBlurFilter.hpp"
+#include "../source/util.h"
+
+NS_GI_BEGIN
+
+REGISTER_FILTER_CLASS(GaussianBlurFilter)
+
+GaussianBlurFilter::GaussianBlurFilter()
+:_hBlurFilter(0)
+,_vBlurFilter(0)
+{
+}
+
+GaussianBlurFilter::~GaussianBlurFilter() {
+ if (_hBlurFilter) {
+ _hBlurFilter->release();
+ _hBlurFilter = 0;
+ }
+
+ if (_vBlurFilter) {
+ _vBlurFilter->release();
+ _vBlurFilter = 0;
+ }
+
+}
+
+GaussianBlurFilter* GaussianBlurFilter::create(int radius/* = 4*/, float sigma/* = 2.0*/) {
+ GaussianBlurFilter* ret = new (std::nothrow) GaussianBlurFilter();
+ if (ret && !ret->init(radius, sigma)) {
+ delete ret;
+ ret = 0;
+ }
+ return ret;
+}
+
+bool GaussianBlurFilter::init(int radius, float sigma) {
+ if (!FilterGroup::init()) {
+ return false;
+ }
+
+ _hBlurFilter = GaussianBlurMonoFilter::create(GaussianBlurMonoFilter::HORIZONTAL, radius, sigma);
+ _vBlurFilter = GaussianBlurMonoFilter::create(GaussianBlurMonoFilter::VERTICAL, radius, sigma);
+ _hBlurFilter->addTarget(_vBlurFilter);
+ addFilter(_hBlurFilter);
+
+ registerProperty("radius", 4, "", [this](int& radius){
+ setRadius(radius);
+ });
+
+ registerProperty("sigma", 2.0, "", [this](float& sigma){
+ setSigma(sigma);
+ });
+
+ return true;
+}
+
+void GaussianBlurFilter::setRadius(int radius) {
+ _hBlurFilter->setRadius(radius);
+ _vBlurFilter->setRadius(radius);
+}
+
+void GaussianBlurFilter::setSigma(float sigma) {
+ _hBlurFilter->setSigma(sigma);
+ _vBlurFilter->setSigma(sigma);
+}
+
+NS_GI_END
diff --git a/filter/src/main/cpp/effect/GaussianBlurFilter.hpp b/filter/src/main/cpp/effect/GaussianBlurFilter.hpp
new file mode 100755
index 0000000..e5488c2
--- /dev/null
+++ b/filter/src/main/cpp/effect/GaussianBlurFilter.hpp
@@ -0,0 +1,48 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef GaussianBlurFilter_hpp
+#define GaussianBlurFilter_hpp
+
+#include "../source/macros.h"
+#include "FilterGroup.hpp"
+#include "GaussianBlurMonoFilter.hpp"
+
+NS_GI_BEGIN
+
+class GaussianBlurFilter : public FilterGroup {
+public:
+ virtual ~GaussianBlurFilter();
+
+ static GaussianBlurFilter* create(int radius = 4, float sigma = 2.0);
+ bool init(int radius, float sigma);
+ void setRadius(int radius);
+ void setSigma(float sigma);
+
+protected:
+ GaussianBlurFilter();
+
+private:
+ GaussianBlurMonoFilter* _hBlurFilter;
+ GaussianBlurMonoFilter* _vBlurFilter;
+};
+
+
+NS_GI_END
+
+#endif /* GaussianBlurFilter_hpp */
diff --git a/filter/src/main/cpp/effect/GaussianBlurMonoFilter.cpp b/filter/src/main/cpp/effect/GaussianBlurMonoFilter.cpp
new file mode 100755
index 0000000..6c2a054
--- /dev/null
+++ b/filter/src/main/cpp/effect/GaussianBlurMonoFilter.cpp
@@ -0,0 +1,329 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include
+#include "GaussianBlurMonoFilter.hpp"
+#include "../source/util.h"
+
+NS_GI_BEGIN
+
+REGISTER_FILTER_CLASS(GaussianBlurMonoFilter)
+
+GaussianBlurMonoFilter::GaussianBlurMonoFilter(Type type/* = HORIZONTAL*/)
+:_type(type)
+,_radius(4)
+,_sigma(2.0)
+{
+}
+
+GaussianBlurMonoFilter* GaussianBlurMonoFilter::create(Type type/* = HORIZONTAL*/, int radius/* = 4*/, float sigma/* = 2.0*/) {
+ GaussianBlurMonoFilter* ret = new (std::nothrow) GaussianBlurMonoFilter(type);
+ if (ret && !ret->init(radius, sigma)) {
+ delete ret;
+ ret = 0;
+ }
+ return ret;
+}
+
+bool GaussianBlurMonoFilter::init(int radius, float sigma) {
+ if (Filter::initWithShaderString(_generateOptimizedVertexShaderString(radius, sigma), _generateOptimizedFragmentShaderString(radius, sigma))) {
+ return true;
+ }
+ return false;
+}
+
+void GaussianBlurMonoFilter::setRadius(int radius) {
+ if (radius == _radius) return;
+
+ _radius = radius;
+
+ if (_filterProgram) {
+ delete _filterProgram;
+ _filterProgram = 0;
+ }
+ initWithShaderString(_generateOptimizedVertexShaderString(_radius, _sigma), _generateOptimizedFragmentShaderString(_radius, _sigma));
+}
+
+void GaussianBlurMonoFilter::setSigma(float sigma) {
+ if (sigma == _sigma) return;
+
+ _sigma = round(sigma);
+
+ int calculatedSampleRadius = 0;
+ if (_sigma >= 1) // Avoid a divide-by-zero error here
+ {
+ // Calculate the number of pixels to sample from by setting a bottom limit for the contribution of the outermost pixel
+ float minimumWeightToFindEdgeOfSamplingArea = 1.0/256.0;
+ calculatedSampleRadius = floor(sqrt(-2.0 * pow(_sigma, 2.0) * log(minimumWeightToFindEdgeOfSamplingArea * sqrt(2.0 * M_PI * pow(_sigma, 2.0))) ));
+ calculatedSampleRadius += calculatedSampleRadius % 2; // There's nothing to gain from handling odd radius sizes, due to the optimizations I use
+ }
+ _radius = calculatedSampleRadius;
+
+ if (_filterProgram) {
+ delete _filterProgram;
+ _filterProgram = 0;
+ }
+ initWithShaderString(_generateOptimizedVertexShaderString(_radius, _sigma), _generateOptimizedFragmentShaderString(_radius, _sigma));
+}
+
+bool GaussianBlurMonoFilter::proceed(bool bUpdateTargets/* = true*/) {
+
+ RotationMode inputRotation = _inputFramebuffers.begin()->second.rotationMode;
+
+ if (rotationSwapsSize(inputRotation))
+ {
+ if (_type == HORIZONTAL) {
+ _filterProgram->setUniformValue("texelWidthOffset", (float)0.0);
+ _filterProgram->setUniformValue("texelHeightOffset", (float)(1.0 / _framebuffer->getWidth()));
+ } else {
+ _filterProgram->setUniformValue("texelWidthOffset", (float)(1.0 / _framebuffer->getHeight()));
+ _filterProgram->setUniformValue("texelHeightOffset", (float)0.0);
+ }
+ } else {
+ if (_type == HORIZONTAL) {
+ _filterProgram->setUniformValue("texelWidthOffset", (float)(1.0 / _framebuffer->getWidth()));
+ _filterProgram->setUniformValue("texelHeightOffset", (float)0.0);
+ } else {
+ _filterProgram->setUniformValue("texelWidthOffset", (float)0.0);
+ _filterProgram->setUniformValue("texelHeightOffset", (float)(1.0 / _framebuffer->getHeight()));
+ }
+ }
+ return Filter::proceed(bUpdateTargets);
+}
+
+std::string GaussianBlurMonoFilter::_generateVertexShaderString(int radius, float sigma) {
+ if (radius < 1 || sigma <= 0.0)
+ {
+ return kDefaultVertexShader;
+ }
+
+ std::string shaderStr =
+ str_format("\
+ attribute vec4 position;\n\
+ attribute vec4 texCoord;\n\
+ uniform float texelWidthOffset;\n\
+ uniform float texelHeightOffset;\n\
+ varying vec2 blurCoordinates[%d];\n\
+ void main()\n\
+ {\n\
+ gl_Position = position;\n\
+ vec2 texelSpacing = vec2(texelWidthOffset, texelHeightOffset);\n\
+ ", radius * 2 + 1);
+
+ for (int i = 0; i < radius * 2 + 1; ++i) {
+ int offsetFromCenter = i - radius;
+ if (offsetFromCenter == 0) {
+ shaderStr = shaderStr + str_format("blurCoordinates[%d] = texCoord.xy;\n", i);
+ } else {
+ shaderStr = shaderStr + str_format("blurCoordinates[%d] = texCoord.xy + texelSpacing * (%f);\n", i, (float)offsetFromCenter);
+ }
+ }
+
+ shaderStr += "}\n";
+
+ return shaderStr;
+}
+
+std::string GaussianBlurMonoFilter::_generateFragmentShaderString(int radius, float sigma) {
+ if (radius < 1 || sigma <= 0.0)
+ {
+ return kDefaultFragmentShader;
+ }
+
+ float* standardGaussianWeights = new float[radius + 1];
+ float sumOfWeights = 0.0;
+ for (int i = 0; i < radius + 1; ++i)
+ {
+ standardGaussianWeights[i] = (1.0 / sqrt(2.0 * PI * pow(sigma, 2.0))) * exp(-pow(i, 2.0) / (2.0 * pow(sigma, 2.0)));
+
+ if (i == 0)
+ {
+ sumOfWeights += standardGaussianWeights[i];
+ } else {
+ sumOfWeights += 2.0 * standardGaussianWeights[i];
+ }
+ }
+ for (int i = 0; i < radius + 1; ++i)
+ {
+ standardGaussianWeights[i] = standardGaussianWeights[i] / sumOfWeights;
+ }
+
+ std::string shaderStr =
+ str_format("\
+ uniform sampler2D colorMap;\n\
+ varying highp vec2 blurCoordinates[%d];\n\
+ void main()\n\
+ {\n\
+ gl_FragColor = vec4(0.0);\n", radius * 2 + 1);
+ for (int i = 0; i < radius * 2 + 1; ++i) {
+ int offsetFromCenter = i - radius;
+ shaderStr += str_format("gl_FragColor += texture2D(colorMap, blurCoordinates[%d]) * %f;\n", i, standardGaussianWeights[abs(offsetFromCenter)]);
+ }
+ shaderStr += "}";
+
+ delete[] standardGaussianWeights; standardGaussianWeights = 0;
+
+ return shaderStr;
+}
+
+std::string GaussianBlurMonoFilter::_generateOptimizedVertexShaderString(int radius, float sigma)
+{
+ if (radius < 1 || sigma <= 0.0)
+ {
+ return kDefaultVertexShader;
+ }
+
+ // 1. generate the normal Gaussian weights for a given sigma
+ float* standardGaussianWeights = new float[radius + 1];
+ float sumOfWeights = 0.0;
+ for (int i = 0; i < radius + 1; ++i)
+ {
+ standardGaussianWeights[i] = (1.0 / sqrt(2.0 * M_PI * pow(sigma, 2.0))) * exp(-pow(i, 2.0) / (2.0 * pow(sigma, 2.0)));
+ if (i == 0)
+ sumOfWeights += standardGaussianWeights[i];
+ else
+ sumOfWeights += 2.0 * standardGaussianWeights[i];
+ }
+
+ // 2. normalize these weights to prevent the clipping of the Gaussian curve at the end of the discrete samples from reducing luminance
+ for (int i = 0; i < radius + 1; ++i)
+ {
+ standardGaussianWeights[i] = standardGaussianWeights[i] / sumOfWeights;
+ }
+
+ // 3. From these weights we calculate the offsets to read interpolated values from
+ int numberOfOptimizedOffsets = fmin(radius / 2 + (radius % 2), 7);
+ float* optimizedGaussianOffsets = new float[numberOfOptimizedOffsets];
+
+ for (int i = 0; i < numberOfOptimizedOffsets; ++i)
+ {
+ GLfloat firstWeight = standardGaussianWeights[i * 2 + 1];
+ GLfloat secondWeight = standardGaussianWeights[i * 2 + 2];
+
+ GLfloat optimizedWeight = firstWeight + secondWeight;
+
+ optimizedGaussianOffsets[i] = (firstWeight * (i * 2 + 1) + secondWeight * (i * 2 + 2)) / optimizedWeight;
+ }
+
+ std::string shaderStr =
+ str_format("\
+ attribute vec4 position;\n\
+ attribute vec4 texCoord;\n\
+ uniform float texelWidthOffset;\n\
+ uniform float texelHeightOffset;\n\
+ varying highp vec2 blurCoordinates[%d];\n\
+ void main()\n\
+ {\n\
+ gl_Position = position;\n\
+ vec2 texelSpacing = vec2(texelWidthOffset, texelHeightOffset);\n\
+ ", numberOfOptimizedOffsets * 2 + 1);
+
+ shaderStr = shaderStr + str_format("blurCoordinates[0] = texCoord.xy;\n");
+ for (int i = 0; i < numberOfOptimizedOffsets; ++i) {
+ shaderStr = shaderStr + str_format(
+ "blurCoordinates[%d] = texCoord.xy + texelSpacing * (%f);\n\
+ blurCoordinates[%d] = texCoord.xy - texelSpacing * (%f);",
+ i * 2 + 1,
+ optimizedGaussianOffsets[i],
+ i * 2 + 2,
+ optimizedGaussianOffsets[i]);
+ }
+
+ shaderStr += "}\n";
+
+ delete[] standardGaussianWeights;
+ delete[] optimizedGaussianOffsets;
+
+ return shaderStr;
+}
+
+std::string GaussianBlurMonoFilter::_generateOptimizedFragmentShaderString(int radius, float sigma)
+{
+ if (radius < 1 || sigma <= 0.0)
+ {
+ return kDefaultFragmentShader;
+ }
+
+ // 1. generate the normal Gaussian weights for a given sigma
+ float* standardGaussianWeights = new float[radius + 1];
+ float sumOfWeights = 0.0;
+ for (int i = 0; i < radius + 1; ++i)
+ {
+ standardGaussianWeights[i] = (1.0 / sqrt(2.0 * M_PI * pow(sigma, 2.0))) * exp(-pow(i, 2.0) / (2.0 * pow(sigma, 2.0)));
+ if (i == 0)
+ sumOfWeights += standardGaussianWeights[i];
+ else
+ sumOfWeights += 2.0 * standardGaussianWeights[i];
+ }
+
+ // 2. normalize these weights to prevent the clipping of the Gaussian curve at the end of the discrete samples from reducing luminance
+ for (int i = 0; i < radius + 1; ++i)
+ {
+ standardGaussianWeights[i] = standardGaussianWeights[i] / sumOfWeights;
+ }
+
+ // 3. From these weights we calculate the offsets to read interpolated values from
+ int trueNumberOfOptimizedOffsets = radius / 2 + (radius % 2);
+ int numberOfOptimizedOffsets = fmin(trueNumberOfOptimizedOffsets, 7);
+
+ std::string shaderStr =
+ str_format("\
+ uniform sampler2D colorMap;\n\
+ uniform highp float texelWidthOffset;\n\
+ uniform highp float texelHeightOffset;\n\
+ varying highp vec2 blurCoordinates[%d];\n\
+ void main()\n\
+ {\n\
+ gl_FragColor = vec4(0.0);\n", numberOfOptimizedOffsets * 2 + 1);
+
+ shaderStr += str_format("gl_FragColor += texture2D(colorMap, blurCoordinates[0]) * %f;\n", standardGaussianWeights[0]);
+ for (int i = 0; i < numberOfOptimizedOffsets; ++i) {
+ float firstWeight = standardGaussianWeights[i * 2 + 1];
+ float secondWeight = standardGaussianWeights[i * 2 + 2];
+ float optimizedWeight = firstWeight + secondWeight;
+
+ shaderStr += str_format("gl_FragColor += texture2D(colorMap, blurCoordinates[%d]) * %f;\n", i * 2 + 1, optimizedWeight);
+ shaderStr += str_format("gl_FragColor += texture2D(colorMap, blurCoordinates[%d]) * %f;\n", i * 2 + 2, optimizedWeight);
+ }
+
+ // If the number of required samples exceeds the amount we can pass in via varyings, we have to do dependent texture reads in the fragment shader
+ if (trueNumberOfOptimizedOffsets > numberOfOptimizedOffsets)
+ {
+ shaderStr += str_format("highp vec2 texelSpacing = vec2(texelWidthOffset, texelHeightOffset);\n");
+
+ for (int i = numberOfOptimizedOffsets; i < trueNumberOfOptimizedOffsets; i++)
+ {
+ float firstWeight = standardGaussianWeights[i * 2 + 1];
+ float secondWeight = standardGaussianWeights[i * 2 + 2];
+
+ float optimizedWeight = firstWeight + secondWeight;
+ float optimizedOffset = (firstWeight * (i * 2 + 1) + secondWeight * (i * 2 + 2)) / optimizedWeight;
+
+ shaderStr += str_format("gl_FragColor += texture2D(colorMap, blurCoordinates[0] + texelSpacing * %f) * %f;\n", optimizedOffset, optimizedWeight);
+
+ shaderStr += str_format("gl_FragColor += texture2D(colorMap, blurCoordinates[0] - texelSpacing * %f) * %f;\n", optimizedOffset, optimizedWeight);
+ }
+ }
+
+ shaderStr += "}";
+
+ delete[] standardGaussianWeights; standardGaussianWeights = 0;
+ return shaderStr;
+}
+
+NS_GI_END
diff --git a/filter/src/main/cpp/effect/GaussianBlurMonoFilter.hpp b/filter/src/main/cpp/effect/GaussianBlurMonoFilter.hpp
new file mode 100755
index 0000000..bd51c0e
--- /dev/null
+++ b/filter/src/main/cpp/effect/GaussianBlurMonoFilter.hpp
@@ -0,0 +1,55 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef GaussianBlurMonoFilter_hpp
+#define GaussianBlurMonoFilter_hpp
+
+#include "../source/macros.h"
+#include "FilterGroup.hpp"
+
+NS_GI_BEGIN
+
+class GaussianBlurMonoFilter : public Filter {
+public:
+ enum Type {HORIZONTAL, VERTICAL};
+
+ static GaussianBlurMonoFilter* create(Type type = HORIZONTAL, int radius = 4, float sigma = 2.0);
+ bool init(int radius, float sigma);
+
+ void setRadius(int radius);
+ void setSigma(float sigma);
+
+ virtual bool proceed(bool bUpdateTargets = true) override;
+protected:
+ GaussianBlurMonoFilter(Type type = HORIZONTAL);
+ Type _type;
+ int _radius;
+ float _sigma;
+
+private:
+ virtual std::string _generateVertexShaderString(int radius, float sigma);
+ virtual std::string _generateFragmentShaderString(int radius, float sigma);
+
+ virtual std::string _generateOptimizedVertexShaderString(int radius, float sigma);
+ virtual std::string _generateOptimizedFragmentShaderString(int radius, float sigma);
+};
+
+
+NS_GI_END
+
+#endif /* GaussianBlurMonoFilter_hpp */
diff --git a/filter/src/main/cpp/effect/GlassSphereFilter.cpp b/filter/src/main/cpp/effect/GlassSphereFilter.cpp
new file mode 100755
index 0000000..ad2369c
--- /dev/null
+++ b/filter/src/main/cpp/effect/GlassSphereFilter.cpp
@@ -0,0 +1,105 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include "GlassSphereFilter.hpp"
+
+USING_NS_GI
+
+REGISTER_FILTER_CLASS(GlassSphereFilter)
+
+const std::string kGlassSphereFragmentShaderString = SHADER_STRING
+(
+
+ uniform sampler2D colorMap;
+ varying highp vec2 vTexCoord;
+
+ uniform highp vec2 center;
+ uniform highp float radius;
+ uniform highp float aspectRatio;
+ uniform highp float refractiveIndex;
+
+ const highp vec3 lightPosition = vec3(-0.5, 0.5, 1.0);
+ const highp vec3 ambientLightPosition = vec3(0.0, 0.0, 1.0);
+
+
+ void main()
+ {
+ highp vec2 textureCoordinateToUse = vec2(vTexCoord.x, (vTexCoord.y * aspectRatio + 0.5 - 0.5 * aspectRatio));
+
+ highp float distanceFromCenter = distance(center, textureCoordinateToUse);
+ lowp float checkForPresenceWithinSphere = step(distanceFromCenter, radius);
+
+ distanceFromCenter = distanceFromCenter / radius;
+
+ highp float normalizedDepth = radius * sqrt(1.0 - distanceFromCenter * distanceFromCenter);
+ highp vec3 sphereNormal = normalize(vec3(textureCoordinateToUse - center, normalizedDepth));
+
+ highp vec3 refractedVector = 2.0 * refract(vec3(0.0, 0.0, -1.0), sphereNormal, refractiveIndex);
+ refractedVector.xy = -refractedVector.xy;
+
+ highp vec3 finalSphereColor = texture2D(colorMap, (refractedVector.xy + 1.0) * 0.5 + center - vec2(0.5)).rgb;
+
+ // Grazing angle lighting
+ highp float lightingIntensity = 2.5 * (1.0 - pow(clamp(dot(ambientLightPosition, sphereNormal), 0.0, 1.0), 0.25));
+ finalSphereColor += lightingIntensity;
+
+ // Specular lighting
+ //lightingIntensity = clamp(dot(normalize(lightPosition), sphereNormal), 0.0, 1.0);
+ //lightingIntensity = pow(lightingIntensity, 15.0);
+ //finalSphereColor += vec3(0.8, 0.8, 0.8) * lightingIntensity;
+
+ gl_FragColor = vec4(finalSphereColor, 1.0) * checkForPresenceWithinSphere;
+ }
+ );
+
+
+
+GlassSphereFilter* GlassSphereFilter::create() {
+ GlassSphereFilter* ret = new (std::nothrow) GlassSphereFilter();
+ if (ret && !ret->init()) {
+ delete ret;
+ ret = 0;
+ }
+ return ret;
+}
+
+bool GlassSphereFilter::init() {
+ if (!initWithFragmentShaderString(kGlassSphereFragmentShaderString)) return false;
+
+ setPositionX(0.5);
+ registerProperty("positionX", _position.x, "The position of x about which to apply the distortion, with a default of 0.5", [this](float& positionX){
+ setPositionX(positionX);
+ });
+
+ setPositionY(0.5);
+ registerProperty("positionY", _position.y, "The position of y about which to apply the distortion, with a default of 0.5", [this](float& positionY){
+ setPositionY(positionY);
+ });
+
+ setRadius(0.25);
+ registerProperty("radius", _radius, "The radius of the distortion, ranging from 0.0 to 1.0, with a default of 0.25", [this](float& radius){
+ setRadius(radius);
+ });
+
+ setRefractiveIndex(0.71);
+ registerProperty("refractiveIndex", _refractiveIndex, "The index of refraction for the sphere, with a default of 0.71", [this](float& refractiveIndex){
+ setRefractiveIndex(refractiveIndex);
+ });
+
+ return true;
+}
diff --git a/filter/src/main/cpp/effect/GlassSphereFilter.hpp b/filter/src/main/cpp/effect/GlassSphereFilter.hpp
new file mode 100755
index 0000000..157c361
--- /dev/null
+++ b/filter/src/main/cpp/effect/GlassSphereFilter.hpp
@@ -0,0 +1,38 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef GlassSphereFilter_hpp
+#define GlassSphereFilter_hpp
+
+#include "../source/macros.h"
+#include "SphereRefractionFilter.hpp"
+
+NS_GI_BEGIN
+
+class GlassSphereFilter : public SphereRefractionFilter {
+public:
+ static GlassSphereFilter* create();
+ bool init();
+
+protected:
+ GlassSphereFilter() {};
+};
+
+NS_GI_END
+
+#endif /* GlassSphereFilter_hpp */
diff --git a/filter/src/main/cpp/effect/GrayscaleFilter.cpp b/filter/src/main/cpp/effect/GrayscaleFilter.cpp
new file mode 100755
index 0000000..9a92a14
--- /dev/null
+++ b/filter/src/main/cpp/effect/GrayscaleFilter.cpp
@@ -0,0 +1,62 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include "GrayscaleFilter.hpp"
+
+NS_GI_BEGIN
+
+REGISTER_FILTER_CLASS(GrayscaleFilter)
+
+const std::string kGrayscaleFragmentShaderString = SHADER_STRING
+(
+ precision highp float;
+ uniform sampler2D colorMap;
+ varying highp vec2 vTexCoord;
+
+ const highp vec3 W = vec3(0.2125, 0.7154, 0.0721);
+
+ void main()
+ {
+ lowp vec4 color = texture2D(colorMap, vTexCoord);
+ float luminance = dot(color.rgb, vec3(0.2125, 0.7154, 0.0721));
+ gl_FragColor = vec4(vec3(luminance), color.a);
+ }
+);
+
+
+GrayscaleFilter* GrayscaleFilter::create() {
+ GrayscaleFilter* ret = new (std::nothrow) GrayscaleFilter();
+ if (ret && !ret->init()) {
+ delete ret;
+ ret = 0;
+ }
+ return ret;
+}
+
+bool GrayscaleFilter::init() {
+ if (Filter::initWithFragmentShaderString(kGrayscaleFragmentShaderString)) {
+ return true;
+ }
+ return false;
+}
+
+bool GrayscaleFilter::proceed(bool bUpdateTargets/* = true*/) {
+ return Filter::proceed(bUpdateTargets);
+}
+
+NS_GI_END
diff --git a/filter/src/main/cpp/effect/GrayscaleFilter.hpp b/filter/src/main/cpp/effect/GrayscaleFilter.hpp
new file mode 100755
index 0000000..a268128
--- /dev/null
+++ b/filter/src/main/cpp/effect/GrayscaleFilter.hpp
@@ -0,0 +1,41 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef GrayscaleFilter_hpp
+#define GrayscaleFilter_hpp
+
+#include "../source/macros.h"
+#include "Filter.hpp"
+
+NS_GI_BEGIN
+
+class GrayscaleFilter : public Filter {
+public:
+ static GrayscaleFilter* create();
+ bool init();
+
+ virtual bool proceed(bool bUpdateTargets = true) override;
+
+protected:
+ GrayscaleFilter() {};
+};
+
+
+NS_GI_END
+
+#endif /* GrayscaleFilter_hpp */
diff --git a/filter/src/main/cpp/effect/HSBFilter.cpp b/filter/src/main/cpp/effect/HSBFilter.cpp
new file mode 100755
index 0000000..e21dc63
--- /dev/null
+++ b/filter/src/main/cpp/effect/HSBFilter.cpp
@@ -0,0 +1,98 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include "HSBFilter.hpp"
+
+NS_GI_BEGIN
+
+REGISTER_FILTER_CLASS(HSBFilter)
+
+/* Matrix algorithms adapted from http://www.graficaobscura.com/matrix/index.html
+
+ Note about luminance vector values below from that page:
+ Where rwgt is 0.3086, gwgt is 0.6094, and bwgt is 0.0820. This is the luminance vector. Notice here that we do not use the standard NTSC weights of 0.299, 0.587, and 0.114. The NTSC weights are only applicable to RGB colors in a gamma 2.2 color space. For linear RGB colors the values above are better.
+ */
+//#define RLUM (0.3086f)
+//#define GLUM (0.6094f)
+//#define BLUM (0.0820f)
+
+/* This is the vector value from the PDF specification, and may be closer to what Photoshop uses */
+#define RLUM (0.3f)
+#define GLUM (0.59f)
+#define BLUM (0.11f)
+
+
+HSBFilter* HSBFilter::create() {
+ HSBFilter* ret = new (std::nothrow) HSBFilter();
+ if (ret && !ret->init()) {
+ delete ret;
+ ret = 0;
+ }
+ return ret;
+}
+
+bool HSBFilter::init() {
+ if (!ColorMatrixFilter::init()) return false;
+ reset();
+
+ return true;
+}
+
+void HSBFilter::reset() {
+ setColorMatrix(Matrix4::IDENTITY);
+}
+
+void HSBFilter::rotateHue(float h){
+ // todo
+}
+
+void HSBFilter::adjustSaturation(float sat) {
+
+ Matrix4 sMat;
+ float rwgt = RLUM;
+ float gwgt = GLUM;
+ float bwgt = BLUM;
+
+ sMat.m[0] = (1.0 - sat) * rwgt + sat;
+ sMat.m[1] = (1.0 - sat) * rwgt;
+ sMat.m[2] = (1.0 - sat) * rwgt;
+ sMat.m[3] = 0.0;
+ sMat.m[4] = (1.0 - sat) * gwgt;
+ sMat.m[5] = (1.0 - sat) * gwgt + sat;
+ sMat.m[6] = (1.0 - sat) * gwgt;
+ sMat.m[7] = 0.0;
+ sMat.m[8] = (1.0 - sat) * bwgt;
+ sMat.m[9] = (1.0 - sat) * bwgt;
+ sMat.m[10] = (1.0 - sat) * bwgt + sat;
+ sMat.m[11] = 0.0;
+ sMat.m[12] = 0.0;
+ sMat.m[13] = 0.0;
+ sMat.m[14] = 0.0;
+ sMat.m[15] = 1.0;
+
+ _colorMatrix = sMat * _colorMatrix;
+}
+
+void HSBFilter::adjustBrightness(float b) {
+ Matrix4 scaleMatrix = Matrix4::IDENTITY;
+ scaleMatrix *= b;
+ _colorMatrix *= scaleMatrix;
+
+}
+
+NS_GI_END
diff --git a/filter/src/main/cpp/effect/HSBFilter.hpp b/filter/src/main/cpp/effect/HSBFilter.hpp
new file mode 100755
index 0000000..24a1d81
--- /dev/null
+++ b/filter/src/main/cpp/effect/HSBFilter.hpp
@@ -0,0 +1,62 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef HSBFilter_hpp
+#define HSBFilter_hpp
+
+#include "../source/macros.h"
+#include "ColorMatrixFilter.hpp"
+
+NS_GI_BEGIN
+
+
+class HSBFilter : public ColorMatrixFilter {
+public:
+ static HSBFilter* create();
+ bool init();
+
+ /** Reset the filter to have no transformations.
+ */
+ void reset();
+
+ /** Add a hue rotation to the filter.
+ The hue rotation is in the range [-360, 360] with 0 being no-change.
+ Note that this adjustment is additive, so use the reset method if you need to.
+ */
+ void rotateHue(float h);
+
+ /** Add a saturation adjustment to the filter.
+ The saturation adjustment is in the range [0.0, 2.0] with 1.0 being no-change.
+ Note that this adjustment is additive, so use the reset method if you need to.
+ */
+ void adjustSaturation(float s);
+
+ /** Add a brightness adjustment to the filter.
+ The brightness adjustment is in the range [0.0, 2.0] with 1.0 being no-change.
+ Note that this adjustment is additive, so use the reset method if you need to.
+ */
+ void adjustBrightness(float b);
+
+protected:
+ HSBFilter() {};
+};
+
+
+NS_GI_END
+
+#endif /* HSBFilter_hpp */
diff --git a/filter/src/main/cpp/effect/HalftoneFilter.cpp b/filter/src/main/cpp/effect/HalftoneFilter.cpp
new file mode 100755
index 0000000..08d28fa
--- /dev/null
+++ b/filter/src/main/cpp/effect/HalftoneFilter.cpp
@@ -0,0 +1,72 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include "HalftoneFilter.hpp"
+
+USING_NS_GI
+
+REGISTER_FILTER_CLASS(HalftoneFilter)
+
+const std::string kHalftoneFragmentShaderString = SHADER_STRING
+(
+ uniform highp float pixelSize;
+ uniform highp float aspectRatio;
+
+ uniform sampler2D colorMap;
+ varying highp vec2 vTexCoord;
+
+ const highp vec3 W = vec3(0.2125, 0.7154, 0.0721);
+
+ void main()
+ {
+ highp vec2 pixelSizeVec = vec2(pixelSize, pixelSize / aspectRatio);
+ highp vec2 samplePos = floor(vTexCoord / pixelSizeVec) * pixelSizeVec + 0.5 * pixelSizeVec;
+
+ highp vec2 textureCoordinateToUse = vec2(vTexCoord.x, (vTexCoord.y * aspectRatio + 0.5 - 0.5 * aspectRatio));
+ highp vec2 adjustedSamplePos = vec2(samplePos.x, (samplePos.y * aspectRatio + 0.5 - 0.5 * aspectRatio));
+ highp float distanceFromSamplePoint = distance(adjustedSamplePos, textureCoordinateToUse);
+ lowp vec3 sampledColor = texture2D(colorMap, samplePos ).rgb;
+ highp float dotScaling = 1.0 - dot(sampledColor, W);
+
+ lowp float checkForPresenceWithinDot = 1.0 - step(distanceFromSamplePoint, (pixelSize * 0.5) * dotScaling);
+
+ gl_FragColor = vec4(vec3(checkForPresenceWithinDot), 1.0);
+ }
+ );
+
+
+
+HalftoneFilter* HalftoneFilter::create() {
+ HalftoneFilter* ret = new (std::nothrow) HalftoneFilter();
+ if (ret && !ret->init()) {
+ delete ret;
+ ret = 0;
+ }
+ return ret;
+}
+
+bool HalftoneFilter::init() {
+ if (!initWithFragmentShaderString(kHalftoneFragmentShaderString)) return false;
+
+ setPixelSize(0.01);
+ registerProperty("pixelSize", _pixelSize, "The size of a pixel that you want to pixellate, ranges from 0 to 0.05.", [this](float& pixelSize){
+ setPixelSize(pixelSize);
+ });
+
+ return true;
+}
diff --git a/filter/src/main/cpp/effect/HalftoneFilter.hpp b/filter/src/main/cpp/effect/HalftoneFilter.hpp
new file mode 100755
index 0000000..b5484ec
--- /dev/null
+++ b/filter/src/main/cpp/effect/HalftoneFilter.hpp
@@ -0,0 +1,38 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef HalftoneFilter_hpp
+#define HalftoneFilter_hpp
+
+#include "../source/macros.h"
+#include "PixellationFilter.hpp"
+
+NS_GI_BEGIN
+
+class HalftoneFilter : public PixellationFilter {
+public:
+ static HalftoneFilter* create();
+ bool init();
+
+protected:
+ HalftoneFilter() {};
+};
+
+NS_GI_END
+
+#endif /* HalftoneFilter_hpp */
diff --git a/filter/src/main/cpp/effect/HueFilter.cpp b/filter/src/main/cpp/effect/HueFilter.cpp
new file mode 100755
index 0000000..48f554a
--- /dev/null
+++ b/filter/src/main/cpp/effect/HueFilter.cpp
@@ -0,0 +1,102 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include "HueFilter.hpp"
+#include
+
+USING_NS_GI
+
+REGISTER_FILTER_CLASS(HueFilter)
+
+// Adapted from http://stackoverflow.com/questions/9234724/how-to-change-hue-of-a-texture-with-glsl - see for code and discussion
+const std::string kHueFragmentShaderString = SHADER_STRING
+(
+ precision highp float;
+ uniform sampler2D colorMap;
+ uniform mediump float hueAdjustment;
+ varying highp vec2 vTexCoord;
+ const highp vec4 kRGBToYPrime = vec4 (0.299, 0.587, 0.114, 0.0);
+ const highp vec4 kRGBToI = vec4 (0.595716, -0.274453, -0.321263, 0.0);
+ const highp vec4 kRGBToQ = vec4 (0.211456, -0.522591, 0.31135, 0.0);
+ const highp vec4 kYIQToR = vec4 (1.0, 0.9563, 0.6210, 0.0);
+ const highp vec4 kYIQToG = vec4 (1.0, -0.2721, -0.6474, 0.0);
+ const highp vec4 kYIQToB = vec4 (1.0, -1.1070, 1.7046, 0.0);
+
+ void main()
+ {
+ // Sample the input pixel
+ highp vec4 color = texture2D(colorMap, vTexCoord);
+
+ // Convert to YIQ
+ highp float YPrime = dot(color, kRGBToYPrime);
+ highp float I = dot(color, kRGBToI);
+ highp float Q = dot(color, kRGBToQ);
+
+ // Calculate the hue and chroma
+ highp float hue = atan(Q, I);
+ highp float chroma = sqrt(I * I + Q * Q);
+
+ // Make the user's adjustments
+ hue += (-hueAdjustment); //why negative rotation?
+
+ // Convert back to YIQ
+ Q = chroma * sin (hue);
+ I = chroma * cos (hue);
+
+ // Convert back to RGB
+ highp vec4 yIQ = vec4 (YPrime, I, Q, 0.0);
+ color.r = dot(yIQ, kYIQToR);
+ color.g = dot(yIQ, kYIQToG);
+ color.b = dot(yIQ, kYIQToB);
+
+ // Save the result
+ gl_FragColor = color;
+ }
+);
+
+
+HueFilter* HueFilter::create() {
+ HueFilter* ret = new (std::nothrow) HueFilter();
+ if (ret && !ret->init()) {
+ delete ret;
+ ret = 0;
+ }
+ return ret;
+}
+
+bool HueFilter::init() {
+ if (!initWithFragmentShaderString(kHueFragmentShaderString)) return false;
+
+ _hueAdjustment = 90;
+ registerProperty("hueAdjustment", _hueAdjustment, "The hueAdjustment (in degree) of the image", [this](float& hueAdjustment){
+ setHueAdjustment(hueAdjustment);
+ });
+
+ return true;
+}
+
+void HueFilter::setHueAdjustment(float hueAdjustment) {
+ // Convert degrees to radians for hue rotation
+ _hueAdjustment = fmodf(hueAdjustment, 360.0) * M_PI/180;
+}
+
+bool HueFilter::proceed(bool bUpdateTargets/* = true*/) {
+ _filterProgram->setUniformValue("hueAdjustment", _hueAdjustment);
+ return Filter::proceed(bUpdateTargets);
+}
+
diff --git a/filter/src/main/cpp/effect/HueFilter.hpp b/filter/src/main/cpp/effect/HueFilter.hpp
new file mode 100755
index 0000000..d9ae895
--- /dev/null
+++ b/filter/src/main/cpp/effect/HueFilter.hpp
@@ -0,0 +1,43 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef HueFilter_hpp
+#define HueFilter_hpp
+
+#include "../source/macros.h"
+#include "Filter.hpp"
+
+NS_GI_BEGIN
+
+class HueFilter : public Filter {
+public:
+ static HueFilter* create();
+ bool init();
+ virtual bool proceed(bool bUpdateTargets = true) override;
+
+ void setHueAdjustment(float hueAdjustment);
+
+protected:
+ HueFilter() {};
+
+ float _hueAdjustment;
+};
+
+NS_GI_END
+
+#endif /* HueFilter_hpp */
diff --git a/filter/src/main/cpp/effect/IOSBlurFilter.cpp b/filter/src/main/cpp/effect/IOSBlurFilter.cpp
new file mode 100755
index 0000000..121291d
--- /dev/null
+++ b/filter/src/main/cpp/effect/IOSBlurFilter.cpp
@@ -0,0 +1,122 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include "IOSBlurFilter.hpp"
+
+NS_GI_BEGIN
+
+REGISTER_FILTER_CLASS(IOSBlurFilter)
+
+IOSBlurFilter::IOSBlurFilter()
+:_saturationFilter(0)
+,_blurFilter(0)
+,_luminanceRangeFilter(0)
+{
+}
+
+IOSBlurFilter::~IOSBlurFilter() {
+ if (_saturationFilter) {
+ _saturationFilter->release();
+ _saturationFilter = 0;
+ }
+
+ if (_blurFilter) {
+ _blurFilter->release();
+ _blurFilter = 0;
+ }
+
+ if (_luminanceRangeFilter) {
+ _luminanceRangeFilter->release();
+ _luminanceRangeFilter = 0;
+ }
+}
+
+IOSBlurFilter* IOSBlurFilter::create() {
+ IOSBlurFilter* ret = new (std::nothrow) IOSBlurFilter();
+ if (ret && !ret->init()) {
+ delete ret;
+ ret = 0;
+ }
+ return ret;
+}
+
+bool IOSBlurFilter::init() {
+ if (!FilterGroup::init()) {
+ return false;
+ }
+
+ _saturationFilter = SaturationFilter::create();
+ _blurFilter = GaussianBlurFilter::create();
+ _luminanceRangeFilter = LuminanceRangeFilter::create();
+
+ _saturationFilter // 1. downsample and desaturate
+ ->addTarget(_blurFilter) // 2. apply a strong Gaussian blur
+ ->addTarget(_luminanceRangeFilter); // 3. upsample and adjust luminance range
+
+ addFilter(_saturationFilter);
+
+ _blurSigma = 12.0;
+ setBlurSigma(_blurSigma);
+ registerProperty("blurSigma", _blurSigma, "", [this](float& blurSigma){
+ setBlurSigma(blurSigma);
+ });
+
+ _saturation = 0.8;
+ setSaturation(_saturation);
+ registerProperty("saturation", _saturation, "", [this](float& saturation){
+ setSaturation(saturation);
+ });
+
+ _rangeReductionFactor = 0.6;
+ setRangeReductionFactor(_rangeReductionFactor);
+ registerProperty("rangeReductionFactor", _rangeReductionFactor, "", [this](float& rangeReductionFactor){
+ setRangeReductionFactor(rangeReductionFactor);
+ });
+
+ _downSampling = 4.0;
+ setDownSampling(_downSampling);
+ registerProperty("downSampling", _downSampling, "", [this](float& downSampling){
+ setDownSampling(downSampling);
+ });
+
+ return true;
+}
+
+
+void IOSBlurFilter::setBlurSigma(float blurSigma) {
+ _blurSigma = blurSigma;
+ _blurFilter->setSigma(blurSigma);
+}
+
+void IOSBlurFilter::setSaturation(float saturation) {
+ _saturation = saturation;
+ _saturationFilter->setSaturation(saturation);
+}
+
+void IOSBlurFilter::setRangeReductionFactor(float rangeReductionFactor) {
+ _rangeReductionFactor = rangeReductionFactor;
+ _luminanceRangeFilter->setRangeReductionFactor(rangeReductionFactor);
+}
+
+void IOSBlurFilter::setDownSampling(float downSampling) {
+ _downSampling = downSampling;
+ _saturationFilter->setFramebufferScale(1 / downSampling);
+ _luminanceRangeFilter->setFramebufferScale(downSampling);
+}
+
+NS_GI_END
diff --git a/filter/src/main/cpp/effect/IOSBlurFilter.hpp b/filter/src/main/cpp/effect/IOSBlurFilter.hpp
new file mode 100755
index 0000000..0dc1a3e
--- /dev/null
+++ b/filter/src/main/cpp/effect/IOSBlurFilter.hpp
@@ -0,0 +1,58 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef IOSBlurFilter_hpp
+#define IOSBlurFilter_hpp
+
+#include "../source/macros.h"
+#include "FilterGroup.hpp"
+#include "SaturationFilter.hpp"
+#include "GaussianBlurFilter.hpp"
+#include "LuminanceRangeFilter.hpp"
+
+NS_GI_BEGIN
+
+class IOSBlurFilter : public FilterGroup {
+public:
+ virtual ~IOSBlurFilter();
+
+ static IOSBlurFilter* create();
+ bool init();
+
+ void setBlurSigma(float blurSigma);
+ void setSaturation(float saturation);
+ void setRangeReductionFactor(float rangeReductionFactor);
+ void setDownSampling(float downSampling);
+
+protected:
+
+ IOSBlurFilter();
+ SaturationFilter* _saturationFilter;
+ GaussianBlurFilter* _blurFilter;
+ LuminanceRangeFilter* _luminanceRangeFilter;
+
+ float _blurSigma;
+ float _saturation;
+ float _rangeReductionFactor;
+ float _downSampling;
+};
+
+
+NS_GI_END
+
+#endif /* IOSBlurFilter_hpp */
diff --git a/filter/src/main/cpp/effect/LuminanceRangeFilter.cpp b/filter/src/main/cpp/effect/LuminanceRangeFilter.cpp
new file mode 100755
index 0000000..7f1a046
--- /dev/null
+++ b/filter/src/main/cpp/effect/LuminanceRangeFilter.cpp
@@ -0,0 +1,73 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include "LuminanceRangeFilter.hpp"
+
+USING_NS_GI
+
+REGISTER_FILTER_CLASS(LuminanceRangeFilter)
+
+const std::string kLuminanceRangeFragmentShaderString = SHADER_STRING
+(
+ uniform sampler2D colorMap;
+ uniform lowp float rangeReductionFactor;
+ varying highp vec2 vTexCoord;
+
+ // Values from "Graphics Shaders: Theory and Practice" by Bailey and Cunningham
+ const mediump vec3 luminanceWeighting = vec3(0.2125, 0.7154, 0.0721);
+
+ void main()
+ {
+ lowp vec4 color = texture2D(colorMap, vTexCoord);
+ mediump float luminance = dot(color.rgb, luminanceWeighting);
+ mediump float luminanceRatio = ((0.5 - luminance) * rangeReductionFactor);
+ gl_FragColor = vec4((color.rgb) + (luminanceRatio), color.a);
+ }
+);
+
+LuminanceRangeFilter* LuminanceRangeFilter::create() {
+ LuminanceRangeFilter* ret = new (std::nothrow) LuminanceRangeFilter();
+ if (ret && !ret->init()) {
+ delete ret;
+ ret = 0;
+ }
+ return ret;
+}
+
+bool LuminanceRangeFilter::init() {
+ if (!initWithFragmentShaderString(kLuminanceRangeFragmentShaderString)) return false;
+
+ _rangeReductionFactor = 0.6;
+ registerProperty("rangeReductionFactor", _rangeReductionFactor, "The degree to reduce the luminance range, from 0.0 to 1.0. Default is 0.6.", [this](float& rangeReductionFactor){
+ setRangeReductionFactor(rangeReductionFactor);
+ });
+
+ return true;
+}
+
+void LuminanceRangeFilter::setRangeReductionFactor(float rangeReductionFactor) {
+ _rangeReductionFactor = rangeReductionFactor;
+ if (_rangeReductionFactor > 1.0) _rangeReductionFactor = 1.0;
+ else if (_rangeReductionFactor < 0.0) _rangeReductionFactor = 0.0;
+}
+
+bool LuminanceRangeFilter::proceed(bool bUpdateTargets/* = true*/) {
+ _filterProgram->setUniformValue("rangeReductionFactor", _rangeReductionFactor);
+ return Filter::proceed(bUpdateTargets);
+}
+
diff --git a/filter/src/main/cpp/effect/LuminanceRangeFilter.hpp b/filter/src/main/cpp/effect/LuminanceRangeFilter.hpp
new file mode 100755
index 0000000..4ea1191
--- /dev/null
+++ b/filter/src/main/cpp/effect/LuminanceRangeFilter.hpp
@@ -0,0 +1,42 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef LuminanceRangeFilter_hpp
+#define LuminanceRangeFilter_hpp
+
+#include "../source/macros.h"
+#include "Filter.hpp"
+
+NS_GI_BEGIN
+
+class LuminanceRangeFilter : public Filter {
+public:
+ static LuminanceRangeFilter* create();
+ bool init();
+ virtual bool proceed(bool bUpdateTargets = true) override;
+
+ void setRangeReductionFactor(float rangeReductionFactor);
+
+protected:
+ LuminanceRangeFilter() {};
+ float _rangeReductionFactor;
+};
+
+NS_GI_END
+
+#endif /* LuminanceRangeFilter_hpp */
diff --git a/filter/src/main/cpp/effect/NearbySampling3x3Filter.cpp b/filter/src/main/cpp/effect/NearbySampling3x3Filter.cpp
new file mode 100755
index 0000000..4849350
--- /dev/null
+++ b/filter/src/main/cpp/effect/NearbySampling3x3Filter.cpp
@@ -0,0 +1,108 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include "NearbySampling3x3Filter.hpp"
+
+
+
+NS_GI_BEGIN
+
+
+
+const std::string kNearbySampling3x3SamplingVertexShaderString = SHADER_STRING
+(
+ attribute vec4 position;
+ attribute vec4 texCoord;
+
+ uniform float texelWidth;
+ uniform float texelHeight;
+
+ varying vec2 vTexCoord;
+ varying vec2 vLeftTexCoord;
+ varying vec2 vRightTexCoord;
+
+ varying vec2 vTopTexCoord;
+ varying vec2 vTopLeftTexCoord;
+ varying vec2 vTopRightTexCoord;
+
+ varying vec2 vBottomTexCoord;
+ varying vec2 vBottomLeftTexCoord;
+ varying vec2 vBottomRightTexCoord;
+
+ void main()
+ {
+ gl_Position = position;
+
+ vec2 widthStep = vec2(texelWidth, 0.0);
+ vec2 heightStep = vec2(0.0, texelHeight);
+ vec2 widthHeightStep = vec2(texelWidth, texelHeight);
+ vec2 widthNegativeHeightStep = vec2(texelWidth, -texelHeight);
+
+ vTexCoord = texCoord.xy;
+ vLeftTexCoord = texCoord.xy - widthStep;
+ vRightTexCoord = texCoord.xy + widthStep;
+
+ vTopTexCoord = texCoord.xy - heightStep;
+ vTopLeftTexCoord = texCoord.xy - widthHeightStep;
+ vTopRightTexCoord = texCoord.xy + widthNegativeHeightStep;
+
+ vBottomTexCoord = texCoord.xy + heightStep;
+ vBottomLeftTexCoord = texCoord.xy - widthNegativeHeightStep;
+ vBottomRightTexCoord = texCoord.xy + widthHeightStep;
+ }
+ );
+
+
+bool NearbySampling3x3Filter::initWithFragmentShaderString(const std::string& fragmentShaderSource, int inputNumber/* = 1*/) {
+ if(Filter::initWithShaderString(kNearbySampling3x3SamplingVertexShaderString, fragmentShaderSource)) {
+ _texelSizeMultiplier = 1.0;
+ _texelWidthUniform = _filterProgram->getUniformLocation("texelWidth");
+ _texelHeightUniform = _filterProgram->getUniformLocation("texelHeight");
+
+ registerProperty("texelSizeMultiplier", _texelSizeMultiplier, "", [this](float& texelSizeMultiplier){
+ setTexelSizeMultiplier(texelSizeMultiplier);
+ });
+
+ return true;
+ }
+ return false;
+}
+
+
+bool NearbySampling3x3Filter::proceed(bool bUpdateTargets/* = true*/) {
+
+ float texelWidth = _texelSizeMultiplier / _framebuffer->getWidth();
+ float texelHeight = _texelSizeMultiplier / _framebuffer->getHeight();
+
+ RotationMode inputRotation = _inputFramebuffers.begin()->second.rotationMode;
+ if (rotationSwapsSize(inputRotation)){
+ texelWidth = _texelSizeMultiplier / _framebuffer->getHeight();
+ texelHeight = _texelSizeMultiplier / _framebuffer->getWidth();
+ }
+
+ _filterProgram->setUniformValue(_texelWidthUniform, texelWidth);
+ _filterProgram->setUniformValue(_texelHeightUniform, texelHeight);
+ return Filter::proceed(bUpdateTargets);
+}
+
+void NearbySampling3x3Filter::setTexelSizeMultiplier(float texelSizeMultiplier) {
+ if (texelSizeMultiplier > 0)
+ _texelSizeMultiplier = texelSizeMultiplier;
+}
+
+NS_GI_END
diff --git a/filter/src/main/cpp/effect/NearbySampling3x3Filter.hpp b/filter/src/main/cpp/effect/NearbySampling3x3Filter.hpp
new file mode 100755
index 0000000..3e1f180
--- /dev/null
+++ b/filter/src/main/cpp/effect/NearbySampling3x3Filter.hpp
@@ -0,0 +1,45 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef NearbySampling3x3Filter_hpp
+#define NearbySampling3x3Filter_hpp
+
+#include "../source/macros.h"
+#include "Filter.hpp"
+
+NS_GI_BEGIN
+
+extern const std::string kNearbySampling3x3SamplingVertexShaderString;
+
+class NearbySampling3x3Filter : public Filter {
+public:
+ virtual bool initWithFragmentShaderString(const std::string& fragmentShaderSource, int inputNumber = 1) override;
+ virtual bool proceed(bool bUpdateTargets = true) override;
+
+ void setTexelSizeMultiplier(float texelSizeMultiplier);
+protected:
+ NearbySampling3x3Filter() {};
+
+ float _texelSizeMultiplier;
+ GLuint _texelWidthUniform;
+ GLuint _texelHeightUniform;
+};
+
+NS_GI_END
+
+#endif /* NearbySampling3x3Filter_hpp */
diff --git a/filter/src/main/cpp/effect/NonMaximumSuppressionFilter.cpp b/filter/src/main/cpp/effect/NonMaximumSuppressionFilter.cpp
new file mode 100755
index 0000000..2b09b0e
--- /dev/null
+++ b/filter/src/main/cpp/effect/NonMaximumSuppressionFilter.cpp
@@ -0,0 +1,88 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include "NonMaximumSuppressionFilter.hpp"
+
+NS_GI_BEGIN
+
+REGISTER_FILTER_CLASS(NonMaximumSuppressionFilter)
+
+const std::string kNonMaximumSuppressionShaderString = SHADER_STRING
+(
+ precision mediump float;
+ uniform sampler2D colorMap;
+
+ varying vec2 vTexCoord;
+ varying vec2 vLeftTexCoord;
+ varying vec2 vRightTexCoord;
+
+ varying vec2 vTopTexCoord;
+ varying vec2 vTopLeftTexCoord;
+ varying vec2 vTopRightTexCoord;
+
+ varying vec2 vBottomTexCoord;
+ varying vec2 vBottomLeftTexCoord;
+ varying vec2 vBottomRightTexCoord;
+
+ void main()
+ {
+ float bottomLeftIntensity = texture2D(colorMap, vBottomLeftTexCoord).r;
+ float topRightIntensity = texture2D(colorMap, vTopRightTexCoord).r;
+ float topLeftIntensity = texture2D(colorMap, vTopLeftTexCoord).r;
+ float bottomRightIntensity = texture2D(colorMap, vBottomRightTexCoord).r;
+ float leftIntensity = texture2D(colorMap, vLeftTexCoord).r;
+ float rightIntensity = texture2D(colorMap, vRightTexCoord).r;
+ float bottomIntensity = texture2D(colorMap, vBottomTexCoord).r;
+ float topIntensity = texture2D(colorMap, vTopTexCoord).r;
+ lowp vec4 centerColor = texture2D(colorMap, vTexCoord);
+
+ // Use a tiebreaker for pixels to the left and immediately above this one
+ lowp float multiplier = 1.0 - step(centerColor.r, topIntensity);
+ multiplier = multiplier * (1.0 - step(centerColor.r, topLeftIntensity));
+ multiplier = multiplier * (1.0 - step(centerColor.r, leftIntensity));
+ multiplier = multiplier * (1.0 - step(centerColor.r, bottomLeftIntensity));
+
+ lowp float maxValue = max(centerColor.r, bottomIntensity);
+ maxValue = max(maxValue, bottomRightIntensity);
+ maxValue = max(maxValue, rightIntensity);
+ maxValue = max(maxValue, topRightIntensity);
+
+ gl_FragColor = vec4((centerColor.rgb * step(maxValue, centerColor.r) * multiplier), 1.0);
+
+ }
+ );
+
+
+NonMaximumSuppressionFilter* NonMaximumSuppressionFilter::create() {
+ NonMaximumSuppressionFilter* ret = new (std::nothrow) NonMaximumSuppressionFilter();
+ if (ret && !ret->init()) {
+ delete ret;
+ ret = 0;
+ }
+ return ret;
+}
+
+bool NonMaximumSuppressionFilter::init() {
+ if (initWithFragmentShaderString(kNonMaximumSuppressionShaderString)) {
+ return true;
+ }
+ return false;
+}
+
+
+NS_GI_END
diff --git a/filter/src/main/cpp/effect/NonMaximumSuppressionFilter.hpp b/filter/src/main/cpp/effect/NonMaximumSuppressionFilter.hpp
new file mode 100755
index 0000000..9734803
--- /dev/null
+++ b/filter/src/main/cpp/effect/NonMaximumSuppressionFilter.hpp
@@ -0,0 +1,40 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef NonMaximumSuppressionFilter_hpp
+#define NonMaximumSuppressionFilter_hpp
+
+#include "../source/macros.h"
+#include "NearbySampling3x3Filter.hpp"
+
+NS_GI_BEGIN
+
+class NonMaximumSuppressionFilter : public NearbySampling3x3Filter {
+public:
+ static NonMaximumSuppressionFilter* create();
+ bool init();
+
+
+protected:
+
+ NonMaximumSuppressionFilter() {};
+};
+
+NS_GI_END
+
+#endif /* NonMaximumSuppressionFilter_hpp */
diff --git a/filter/src/main/cpp/effect/PixellationFilter.cpp b/filter/src/main/cpp/effect/PixellationFilter.cpp
new file mode 100755
index 0000000..0172575
--- /dev/null
+++ b/filter/src/main/cpp/effect/PixellationFilter.cpp
@@ -0,0 +1,86 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include "PixellationFilter.hpp"
+
+USING_NS_GI
+
+REGISTER_FILTER_CLASS(PixellationFilter)
+
+const std::string kPixellationFragmentShaderString = SHADER_STRING
+(
+ uniform highp float pixelSize;
+ uniform highp float aspectRatio;
+
+ uniform sampler2D colorMap;
+ varying highp vec2 vTexCoord;
+
+ void main()
+ {
+ highp vec2 pixelSizeVec = vec2(pixelSize, pixelSize / aspectRatio);
+ highp vec2 samplePos = floor(vTexCoord / pixelSizeVec) * pixelSizeVec + 0.5 * pixelSizeVec;
+ gl_FragColor = texture2D(colorMap, samplePos);
+ }
+ );
+
+
+PixellationFilter* PixellationFilter::create() {
+ PixellationFilter* ret = new (std::nothrow) PixellationFilter();
+ if (ret && !ret->init()) {
+ delete ret;
+ ret = 0;
+ }
+ return ret;
+}
+
+bool PixellationFilter::init() {
+ if (!initWithFragmentShaderString(kPixellationFragmentShaderString)) return false;
+
+ _pixelSize = 0.1;
+ registerProperty("pixelSize", _pixelSize, "The size of a pixel that you want to pixellate, ranges from 0 to 1.", [this](float& pixelSize){
+ setPixelSize(pixelSize);
+ });
+
+ return true;
+}
+
+void PixellationFilter::setPixelSize(float pixelSize) {
+ _pixelSize = pixelSize;
+ if (_pixelSize > 1.0) _pixelSize = 1.0;
+ else if (_pixelSize < 0.0) _pixelSize = 0.0;
+
+}
+
+bool PixellationFilter::proceed(bool bUpdateTargets/* = true*/) {
+
+ float aspectRatio = 1.0;
+ Framebuffer* firstInputFramebuffer = _inputFramebuffers.begin()->second.frameBuffer;
+ aspectRatio = firstInputFramebuffer->getHeight() / (float)(firstInputFramebuffer->getWidth());
+ _filterProgram->setUniformValue("aspectRatio", aspectRatio);
+
+ float pixelSize = _pixelSize;
+ float singlePixelWidth = 1.0 / firstInputFramebuffer->getWidth();
+ if (pixelSize < singlePixelWidth)
+ {
+ pixelSize = singlePixelWidth;
+ }
+ _filterProgram->setUniformValue("pixelSize", pixelSize);
+
+ return Filter::proceed(bUpdateTargets);
+}
+
diff --git a/filter/src/main/cpp/effect/PixellationFilter.hpp b/filter/src/main/cpp/effect/PixellationFilter.hpp
new file mode 100755
index 0000000..5907610
--- /dev/null
+++ b/filter/src/main/cpp/effect/PixellationFilter.hpp
@@ -0,0 +1,43 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef PixellationFilter_hpp
+#define PixellationFilter_hpp
+
+#include "../source/macros.h"
+#include "Filter.hpp"
+
+NS_GI_BEGIN
+
+class PixellationFilter : public Filter {
+public:
+ static PixellationFilter* create();
+ bool init();
+ virtual bool proceed(bool bUpdateTargets = true) override;
+
+ void setPixelSize(float pixelSize);
+
+protected:
+ PixellationFilter() {};
+
+ float _pixelSize;
+};
+
+NS_GI_END
+
+#endif /* PixellationFilter_hpp */
diff --git a/filter/src/main/cpp/effect/PosterizeFilter.cpp b/filter/src/main/cpp/effect/PosterizeFilter.cpp
new file mode 100755
index 0000000..0b2817c
--- /dev/null
+++ b/filter/src/main/cpp/effect/PosterizeFilter.cpp
@@ -0,0 +1,70 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include "PosterizeFilter.hpp"
+
+USING_NS_GI
+
+REGISTER_FILTER_CLASS(PosterizeFilter)
+
+const std::string kPosterizeFragmentShaderString = SHADER_STRING
+(
+ uniform sampler2D colorMap;
+ uniform highp float colorLevels;
+ varying highp vec2 vTexCoord;
+
+ void main()
+ {
+ lowp vec4 color = texture2D(colorMap, vTexCoord);
+
+ gl_FragColor = floor((color * colorLevels) + vec4(0.5)) / colorLevels;
+ }
+);
+
+
+PosterizeFilter* PosterizeFilter::create() {
+ PosterizeFilter* ret = new (std::nothrow) PosterizeFilter();
+ if (ret && !ret->init()) {
+ delete ret;
+ ret = 0;
+ }
+ return ret;
+}
+
+bool PosterizeFilter::init() {
+ if (!initWithFragmentShaderString(kPosterizeFragmentShaderString)) return false;
+
+ _colorLevels = 10;
+ registerProperty("colorLevels", _colorLevels, "The number of color levels to reduce the image space to. This ranges from 1 to 256, with a default of 10.", [this](int& colorLevels){
+ setColorLevels(colorLevels);
+ });
+
+ return true;
+}
+
+void PosterizeFilter::setColorLevels(int colorLevels) {
+ _colorLevels = colorLevels;
+ if (_colorLevels > 256) _colorLevels = 256;
+ else if (_colorLevels < 1) _colorLevels = 1;
+}
+
+bool PosterizeFilter::proceed(bool bUpdateTargets/* = true*/) {
+ _filterProgram->setUniformValue("colorLevels", (float)_colorLevels);
+ return Filter::proceed(bUpdateTargets);
+}
+
diff --git a/filter/src/main/cpp/effect/PosterizeFilter.hpp b/filter/src/main/cpp/effect/PosterizeFilter.hpp
new file mode 100755
index 0000000..88488fa
--- /dev/null
+++ b/filter/src/main/cpp/effect/PosterizeFilter.hpp
@@ -0,0 +1,43 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef PosterizeFilter_hpp
+#define PosterizeFilter_hpp
+
+#include "../source/macros.h"
+#include "Filter.hpp"
+
+NS_GI_BEGIN
+
+class PosterizeFilter : public Filter {
+public:
+ static PosterizeFilter* create();
+ bool init();
+ virtual bool proceed(bool bUpdateTargets = true) override;
+
+ void setColorLevels(int colorLevels);
+
+protected:
+ PosterizeFilter() {};
+
+ int _colorLevels;
+};
+
+NS_GI_END
+
+#endif /* PosterizeFilter_hpp */
diff --git a/filter/src/main/cpp/effect/RGBFilter.cpp b/filter/src/main/cpp/effect/RGBFilter.cpp
new file mode 100755
index 0000000..012e73b
--- /dev/null
+++ b/filter/src/main/cpp/effect/RGBFilter.cpp
@@ -0,0 +1,92 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include "RGBFilter.hpp"
+
+USING_NS_GI
+
+REGISTER_FILTER_CLASS(RGBFilter)
+
+const std::string kRGBFragmentShaderString = SHADER_STRING
+(
+ uniform sampler2D colorMap;
+ uniform highp float redAdjustment;
+ uniform highp float greenAdjustment;
+ uniform highp float blueAdjustment;
+ varying highp vec2 vTexCoord;
+
+ void main()
+ {
+ lowp vec4 color = texture2D(colorMap, vTexCoord);
+ gl_FragColor = vec4(color.r * redAdjustment, color.g * greenAdjustment, color.b * blueAdjustment, color.a);
+ }
+);
+
+
+RGBFilter* RGBFilter::create() {
+ RGBFilter* ret = new (std::nothrow) RGBFilter();
+ if (ret && !ret->init()) {
+ delete ret;
+ ret = 0;
+ }
+ return ret;
+}
+
+bool RGBFilter::init() {
+ if (!initWithFragmentShaderString(kRGBFragmentShaderString)) return false;
+
+ _redAdjustment = 1.0;
+ _greenAdjustment = 1.0;
+ _blueAdjustment = 1.0;
+
+ registerProperty("redAdjustment", _redAdjustment, "The red adjustment of the image.The range is from 0.0 up, with 1.0 as the default.", [this](float& redAdjustment){
+ setRedAdjustment(redAdjustment);
+ });
+
+ registerProperty("greenAdjustment", _greenAdjustment, "The green adjustment of the image.The range is from 0.0 up, with 1.0 as the default.", [this](float& greenAdjustment){
+ setGreenAdjustment(greenAdjustment);
+ });
+
+ registerProperty("blueAdjustment", _blueAdjustment, "The blue adjustment of the image.The range is from 0.0 up, with 1.0 as the default.", [this](float& blueAdjustment){
+ setBlueAdjustment(blueAdjustment);
+ });
+
+ return true;
+}
+
+void RGBFilter::setRedAdjustment(float redAdjustment) {
+ _redAdjustment = redAdjustment;
+ if (_redAdjustment < 0.0) _redAdjustment = 0.0;
+}
+
+void RGBFilter::setGreenAdjustment(float greenAdjustment) {
+ _greenAdjustment = greenAdjustment;
+ if (_greenAdjustment < 0.0) _greenAdjustment = 0.0;
+}
+
+void RGBFilter::setBlueAdjustment(float blueAdjustment) {
+ _blueAdjustment = blueAdjustment;
+ if (_blueAdjustment < 0.0) _blueAdjustment = 0.0;
+}
+bool RGBFilter::proceed(bool bUpdateTargets/* = true*/) {
+ _filterProgram->setUniformValue("redAdjustment", _redAdjustment);
+ _filterProgram->setUniformValue("greenAdjustment", _greenAdjustment);
+ _filterProgram->setUniformValue("blueAdjustment", _blueAdjustment);
+ return Filter::proceed(bUpdateTargets);
+}
+
diff --git a/filter/src/main/cpp/effect/RGBFilter.hpp b/filter/src/main/cpp/effect/RGBFilter.hpp
new file mode 100755
index 0000000..b839a9c
--- /dev/null
+++ b/filter/src/main/cpp/effect/RGBFilter.hpp
@@ -0,0 +1,47 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef RGBFilter_hpp
+#define RGBFilter_hpp
+
+#include "../source/macros.h"
+#include "Filter.hpp"
+
+NS_GI_BEGIN
+
+class RGBFilter : public Filter {
+public:
+ static RGBFilter* create();
+ bool init();
+ virtual bool proceed(bool bUpdateTargets = true) override;
+
+ void setRedAdjustment(float redAdjustment);
+ void setGreenAdjustment(float greenAdjustment);
+ void setBlueAdjustment(float blueAdjustment);
+
+protected:
+ RGBFilter() {};
+
+ float _redAdjustment;
+ float _greenAdjustment;
+ float _blueAdjustment;
+};
+
+NS_GI_END
+
+#endif /* RGBFilter_hpp */
diff --git a/filter/src/main/cpp/effect/SaturationFilter.cpp b/filter/src/main/cpp/effect/SaturationFilter.cpp
new file mode 100755
index 0000000..f9b4b8e
--- /dev/null
+++ b/filter/src/main/cpp/effect/SaturationFilter.cpp
@@ -0,0 +1,75 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include "SaturationFilter.hpp"
+
+USING_NS_GI
+
+REGISTER_FILTER_CLASS(SaturationFilter)
+
+const std::string kSaturationFragmentShaderString = SHADER_STRING
+(
+ uniform sampler2D colorMap;
+ uniform lowp float saturation;
+ varying highp vec2 vTexCoord;
+
+ // Values from "Graphics Shaders: Theory and Practice" by Bailey and Cunningham
+ const mediump vec3 luminanceWeighting = vec3(0.2125, 0.7154, 0.0721);
+
+ void main()
+ {
+ lowp vec4 color = texture2D(colorMap, vTexCoord);
+ lowp float luminance = dot(color.rgb, luminanceWeighting);
+ lowp vec3 greyScaleColor = vec3(luminance);
+
+ gl_FragColor = vec4(mix(greyScaleColor, color.rgb, saturation), color.a);
+ }
+);
+
+
+SaturationFilter* SaturationFilter::create() {
+ SaturationFilter* ret = new (std::nothrow) SaturationFilter();
+ if (ret && !ret->init()) {
+ delete ret;
+ ret = 0;
+ }
+ return ret;
+}
+
+bool SaturationFilter::init() {
+ if (!initWithFragmentShaderString(kSaturationFragmentShaderString)) return false;
+
+ _saturation = 1.0;
+ registerProperty("saturation", _saturation, "The saturation of an image. Saturation ranges from 0.0 (fully desaturated) to 2.0 (max saturation), with 1.0 as the normal level", [this](float& saturation){
+ setSaturation(saturation);
+ });
+
+ return true;
+}
+
+void SaturationFilter::setSaturation(float saturation) {
+ _saturation = saturation;
+ if (_saturation > 2.0) _saturation = 2.0;
+ else if (_saturation < 0.0) _saturation = 0.0;
+}
+
+bool SaturationFilter::proceed(bool bUpdateTargets/* = true*/) {
+ _filterProgram->setUniformValue("saturation", _saturation);
+ return Filter::proceed(bUpdateTargets);
+}
+
diff --git a/filter/src/main/cpp/effect/SaturationFilter.hpp b/filter/src/main/cpp/effect/SaturationFilter.hpp
new file mode 100755
index 0000000..853ab10
--- /dev/null
+++ b/filter/src/main/cpp/effect/SaturationFilter.hpp
@@ -0,0 +1,43 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef SaturationFilter_hpp
+#define SaturationFilter_hpp
+
+#include "../source/macros.h"
+#include "Filter.hpp"
+
+NS_GI_BEGIN
+
+class SaturationFilter : public Filter {
+public:
+ static SaturationFilter* create();
+ bool init();
+ virtual bool proceed(bool bUpdateTargets = true) override;
+
+ void setSaturation(float saturation);
+
+protected:
+ SaturationFilter() {};
+
+ float _saturation;
+};
+
+NS_GI_END
+
+#endif /* SaturationFilter_hpp */
diff --git a/filter/src/main/cpp/effect/SingleComponentGaussianBlurFilter.cpp b/filter/src/main/cpp/effect/SingleComponentGaussianBlurFilter.cpp
new file mode 100755
index 0000000..8f9b6e4
--- /dev/null
+++ b/filter/src/main/cpp/effect/SingleComponentGaussianBlurFilter.cpp
@@ -0,0 +1,86 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include
+#include "SingleComponentGaussianBlurFilter.hpp"
+#include "../source/util.h"
+
+NS_GI_BEGIN
+
+REGISTER_FILTER_CLASS(SingleComponentGaussianBlurFilter)
+
+SingleComponentGaussianBlurFilter::SingleComponentGaussianBlurFilter()
+:_hBlurFilter(0)
+,_vBlurFilter(0)
+{
+}
+
+SingleComponentGaussianBlurFilter::~SingleComponentGaussianBlurFilter() {
+ if (_hBlurFilter) {
+ _hBlurFilter->release();
+ _hBlurFilter = 0;
+ }
+
+ if (_vBlurFilter) {
+ _vBlurFilter->release();
+ _vBlurFilter = 0;
+ }
+
+}
+
+SingleComponentGaussianBlurFilter* SingleComponentGaussianBlurFilter::create(int radius/* = 4*/, float sigma/* = 2.0*/) {
+ SingleComponentGaussianBlurFilter* ret = new (std::nothrow) SingleComponentGaussianBlurFilter();
+ if (ret && !ret->init(radius, sigma)) {
+ delete ret;
+ ret = 0;
+ }
+ return ret;
+}
+
+bool SingleComponentGaussianBlurFilter::init(int radius, float sigma) {
+ if (!FilterGroup::init()) {
+ return false;
+ }
+
+ _hBlurFilter = SingleComponentGaussianBlurMonoFilter::create(SingleComponentGaussianBlurMonoFilter::HORIZONTAL, radius, sigma);
+ _vBlurFilter = SingleComponentGaussianBlurMonoFilter::create(SingleComponentGaussianBlurMonoFilter::VERTICAL, radius, sigma);
+ _hBlurFilter->addTarget(_vBlurFilter);
+ addFilter(_hBlurFilter);
+
+ registerProperty("radius", 4, "", [this](int& radius){
+ setRadius(radius);
+ });
+
+ registerProperty("sigma", 2.0, "", [this](float& sigma){
+ setSigma(sigma);
+ });
+
+ return true;
+}
+
+void SingleComponentGaussianBlurFilter::setRadius(int radius) {
+ _hBlurFilter->setRadius(radius);
+ _vBlurFilter->setRadius(radius);
+}
+
+void SingleComponentGaussianBlurFilter::setSigma(float sigma) {
+ _hBlurFilter->setSigma(sigma);
+ _vBlurFilter->setSigma(sigma);
+}
+
+NS_GI_END
diff --git a/filter/src/main/cpp/effect/SingleComponentGaussianBlurFilter.hpp b/filter/src/main/cpp/effect/SingleComponentGaussianBlurFilter.hpp
new file mode 100755
index 0000000..1e6cb60
--- /dev/null
+++ b/filter/src/main/cpp/effect/SingleComponentGaussianBlurFilter.hpp
@@ -0,0 +1,48 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef SingleComponentGaussianBlurFilter_hpp
+#define SingleComponentGaussianBlurFilter_hpp
+
+#include "../source/macros.h"
+#include "FilterGroup.hpp"
+#include "SingleComponentGaussianBlurMonoFilter.hpp"
+
+NS_GI_BEGIN
+
+class SingleComponentGaussianBlurFilter : public FilterGroup {
+public:
+ virtual ~SingleComponentGaussianBlurFilter();
+
+ static SingleComponentGaussianBlurFilter* create(int radius = 4, float sigma = 2.0);
+ bool init(int radius, float sigma);
+ void setRadius(int radius);
+ void setSigma(float sigma);
+
+protected:
+ SingleComponentGaussianBlurFilter();
+
+private:
+ SingleComponentGaussianBlurMonoFilter* _hBlurFilter;
+ SingleComponentGaussianBlurMonoFilter* _vBlurFilter;
+};
+
+
+NS_GI_END
+
+#endif /* GaussianBlurFilter_hpp */
diff --git a/filter/src/main/cpp/effect/SingleComponentGaussianBlurMonoFilter.cpp b/filter/src/main/cpp/effect/SingleComponentGaussianBlurMonoFilter.cpp
new file mode 100755
index 0000000..810e88e
--- /dev/null
+++ b/filter/src/main/cpp/effect/SingleComponentGaussianBlurMonoFilter.cpp
@@ -0,0 +1,187 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include "SingleComponentGaussianBlurMonoFilter.hpp"
+#include
+
+NS_GI_BEGIN
+
+REGISTER_FILTER_CLASS(SingleComponentGaussianBlurMonoFilter)
+
+SingleComponentGaussianBlurMonoFilter::SingleComponentGaussianBlurMonoFilter(Type type/* = HORIZONTAL*/)
+:GaussianBlurMonoFilter(type)
+{
+}
+
+SingleComponentGaussianBlurMonoFilter* SingleComponentGaussianBlurMonoFilter::create(Type type/* = HORIZONTAL*/, int radius/* = 4*/, float sigma/* = 2.0*/) {
+ SingleComponentGaussianBlurMonoFilter* ret = new (std::nothrow) SingleComponentGaussianBlurMonoFilter(type);
+ if (ret && !ret->init(radius, sigma)) {
+ delete ret;
+ ret = 0;
+ }
+ return ret;
+}
+
+std::string SingleComponentGaussianBlurMonoFilter::_generateOptimizedVertexShaderString(int radius, float sigma)
+{
+ if (radius < 1 || sigma <= 0.0)
+ {
+ return kDefaultVertexShader;
+ }
+
+ // 1. generate the normal Gaussian weights for a given sigma
+ float* standardGaussianWeights = new float[radius + 1];
+ float sumOfWeights = 0.0;
+ for (int i = 0; i < radius + 1; ++i)
+ {
+ standardGaussianWeights[i] = (1.0 / sqrt(2.0 * M_PI * pow(sigma, 2.0))) * exp(-pow(i, 2.0) / (2.0 * pow(sigma, 2.0)));
+ if (i == 0)
+ sumOfWeights += standardGaussianWeights[i];
+ else
+ sumOfWeights += 2.0 * standardGaussianWeights[i];
+ }
+
+ // 2. normalize these weights to prevent the clipping of the Gaussian curve at the end of the discrete samples from reducing luminance
+ for (int i = 0; i < radius + 1; ++i)
+ {
+ standardGaussianWeights[i] = standardGaussianWeights[i] / sumOfWeights;
+ }
+
+ // 3. From these weights we calculate the offsets to read interpolated values from
+ int numberOfOptimizedOffsets = fmin(radius / 2 + (radius % 2), 7);
+ float* optimizedGaussianOffsets = new float[numberOfOptimizedOffsets];
+
+ for (int i = 0; i < numberOfOptimizedOffsets; ++i)
+ {
+ GLfloat firstWeight = standardGaussianWeights[i * 2 + 1];
+ GLfloat secondWeight = standardGaussianWeights[i * 2 + 2];
+
+ GLfloat optimizedWeight = firstWeight + secondWeight;
+
+ optimizedGaussianOffsets[i] = (firstWeight * (i * 2 + 1) + secondWeight * (i * 2 + 2)) / optimizedWeight;
+ }
+
+ std::string shaderStr =
+ str_format("\
+ attribute vec4 position;\n\
+ attribute vec4 texCoord;\n\
+ uniform float texelWidthOffset;\n\
+ uniform float texelHeightOffset;\n\
+ varying highp vec2 blurCoordinates[%d];\n\
+ void main()\n\
+ {\n\
+ gl_Position = position;\n\
+ vec2 texelSpacing = vec2(texelWidthOffset, texelHeightOffset);\n\
+ ", numberOfOptimizedOffsets * 2 + 1);
+
+ shaderStr = shaderStr + str_format("blurCoordinates[0] = texCoord.xy;\n");
+ for (int i = 0; i < numberOfOptimizedOffsets; ++i) {
+ shaderStr = shaderStr + str_format(
+ "blurCoordinates[%d] = texCoord.xy + texelSpacing * (%f);\n\
+ blurCoordinates[%d] = texCoord.xy - texelSpacing * (%f);",
+ i * 2 + 1,
+ optimizedGaussianOffsets[i],
+ i * 2 + 2,
+ optimizedGaussianOffsets[i]);
+ }
+
+ shaderStr += "}\n";
+
+ delete[] standardGaussianWeights;
+ delete[] optimizedGaussianOffsets;
+
+ return shaderStr;
+}
+
+std::string SingleComponentGaussianBlurMonoFilter::_generateOptimizedFragmentShaderString(int radius, float sigma)
+{
+ if (radius < 1 || sigma <= 0.0)
+ {
+ return kDefaultFragmentShader;
+ }
+
+ // 1. generate the normal Gaussian weights for a given sigma
+ float* standardGaussianWeights = new float[radius + 1];
+ float sumOfWeights = 0.0;
+ for (int i = 0; i < radius + 1; ++i)
+ {
+ standardGaussianWeights[i] = (1.0 / sqrt(2.0 * M_PI * pow(sigma, 2.0))) * exp(-pow(i, 2.0) / (2.0 * pow(sigma, 2.0)));
+ if (i == 0)
+ sumOfWeights += standardGaussianWeights[i];
+ else
+ sumOfWeights += 2.0 * standardGaussianWeights[i];
+ }
+
+ // 2. normalize these weights to prevent the clipping of the Gaussian curve at the end of the discrete samples from reducing luminance
+ for (int i = 0; i < radius + 1; ++i)
+ {
+ standardGaussianWeights[i] = standardGaussianWeights[i] / sumOfWeights;
+ }
+
+ // 3. From these weights we calculate the offsets to read interpolated values from
+ int trueNumberOfOptimizedOffsets = radius / 2 + (radius % 2);
+ int numberOfOptimizedOffsets = fmin(trueNumberOfOptimizedOffsets, 7);
+
+ std::string shaderStr =
+ str_format("\
+ uniform sampler2D colorMap;\n\
+ uniform highp float texelWidthOffset;\n\
+ uniform highp float texelHeightOffset;\n\
+ varying highp vec2 blurCoordinates[%d];\n\
+ void main()\n\
+ {\n\
+ lowp float sum = 0.0;\n", numberOfOptimizedOffsets * 2 + 1);
+
+ shaderStr += str_format("gl_FragColor += texture2D(colorMap, blurCoordinates[0]) * %f;\n", standardGaussianWeights[0]);
+ for (int i = 0; i < numberOfOptimizedOffsets; ++i) {
+ float firstWeight = standardGaussianWeights[i * 2 + 1];
+ float secondWeight = standardGaussianWeights[i * 2 + 2];
+ float optimizedWeight = firstWeight + secondWeight;
+
+ shaderStr += str_format("sum += texture2D(colorMap, blurCoordinates[%d]).r * %f;\n", i * 2 + 1, optimizedWeight);
+ shaderStr += str_format("sum += texture2D(colorMap, blurCoordinates[%d]).r * %f;\n", i * 2 + 2, optimizedWeight);
+ }
+
+ // If the number of required samples exceeds the amount we can pass in via varyings, we have to do dependent texture reads in the fragment shader
+ if (trueNumberOfOptimizedOffsets > numberOfOptimizedOffsets)
+ {
+ shaderStr += str_format("highp vec2 texelSpacing = vec2(texelWidthOffset, texelHeightOffset);\n");
+
+ for (int i = numberOfOptimizedOffsets; i < trueNumberOfOptimizedOffsets; i++)
+ {
+ float firstWeight = standardGaussianWeights[i * 2 + 1];
+ float secondWeight = standardGaussianWeights[i * 2 + 2];
+
+ float optimizedWeight = firstWeight + secondWeight;
+ float optimizedOffset = (firstWeight * (i * 2 + 1) + secondWeight * (i * 2 + 2)) / optimizedWeight;
+
+ shaderStr += str_format("sum += texture2D(colorMap, blurCoordinates[0] + texelSpacing * %f).r * %f;\n", optimizedOffset, optimizedWeight);
+
+ shaderStr += str_format("sum += texture2D(colorMap, blurCoordinates[0] - texelSpacing * %f).r * %f;\n", optimizedOffset, optimizedWeight);
+ }
+ }
+
+ shaderStr +=
+ "gl_FragColor = vec4(sum, sum, sum, 1.0);\n\
+ }";
+
+ delete[] standardGaussianWeights; standardGaussianWeights = 0;
+ return shaderStr;
+}
+
+NS_GI_END
diff --git a/filter/src/main/cpp/effect/SingleComponentGaussianBlurMonoFilter.hpp b/filter/src/main/cpp/effect/SingleComponentGaussianBlurMonoFilter.hpp
new file mode 100755
index 0000000..caf13f7
--- /dev/null
+++ b/filter/src/main/cpp/effect/SingleComponentGaussianBlurMonoFilter.hpp
@@ -0,0 +1,43 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef SingleComponentGaussianBlurMonoFilter_hpp
+#define SingleComponentGaussianBlurMonoFilter_hpp
+
+#include "../source/macros.h"
+#include "GaussianBlurMonoFilter.hpp"
+
+NS_GI_BEGIN
+
+class SingleComponentGaussianBlurMonoFilter : public GaussianBlurMonoFilter {
+public:
+
+ static SingleComponentGaussianBlurMonoFilter* create(Type type = HORIZONTAL, int radius = 4, float sigma = 2.0);
+
+protected:
+ SingleComponentGaussianBlurMonoFilter(Type type = HORIZONTAL);
+
+private:
+ std::string _generateOptimizedVertexShaderString(int radius, float sigma) override;
+ std::string _generateOptimizedFragmentShaderString(int radius, float sigma) override;
+};
+
+
+NS_GI_END
+
+#endif /* SingleComponentGaussianBlurMonoFilter_hpp */
diff --git a/filter/src/main/cpp/effect/SketchFilter.cpp b/filter/src/main/cpp/effect/SketchFilter.cpp
new file mode 100755
index 0000000..1b7f260
--- /dev/null
+++ b/filter/src/main/cpp/effect/SketchFilter.cpp
@@ -0,0 +1,149 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include "SketchFilter.hpp"
+
+NS_GI_BEGIN
+
+REGISTER_FILTER_CLASS(SketchFilter)
+
+const std::string kSketchFilterFragmentShaderString = SHADER_STRING
+(
+ precision mediump float;
+ uniform sampler2D colorMap;
+ uniform float edgeStrength;
+
+ varying vec2 vTexCoord;
+ varying vec2 vLeftTexCoord;
+ varying vec2 vRightTexCoord;
+
+ varying vec2 vTopTexCoord;
+ varying vec2 vTopLeftTexCoord;
+ varying vec2 vTopRightTexCoord;
+
+ varying vec2 vBottomTexCoord;
+ varying vec2 vBottomLeftTexCoord;
+ varying vec2 vBottomRightTexCoord;
+
+ void main()
+ {
+ float bottomLeftIntensity = texture2D(colorMap, vBottomLeftTexCoord).r;
+ float topRightIntensity = texture2D(colorMap, vTopRightTexCoord).r;
+ float topLeftIntensity = texture2D(colorMap, vTopLeftTexCoord).r;
+ float bottomRightIntensity = texture2D(colorMap, vBottomRightTexCoord).r;
+ float leftIntensity = texture2D(colorMap, vLeftTexCoord).r;
+ float rightIntensity = texture2D(colorMap, vRightTexCoord).r;
+ float bottomIntensity = texture2D(colorMap, vBottomTexCoord).r;
+ float topIntensity = texture2D(colorMap, vTopTexCoord).r;
+ float h = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + bottomLeftIntensity + 2.0 * bottomIntensity + bottomRightIntensity;
+ float v = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomRightIntensity + 2.0 * rightIntensity + topRightIntensity;
+
+ float mag = 1.0 - length(vec2(h, v)) * edgeStrength;
+ gl_FragColor = vec4(vec3(mag), 1.0);
+ }
+ );
+
+SketchFilter::SketchFilter()
+:_grayscaleFilter(0)
+,_sketchFilter(0)
+{
+
+}
+
+SketchFilter::~SketchFilter()
+{
+ if (_grayscaleFilter) {
+ _grayscaleFilter->release();
+ _grayscaleFilter = 0;
+ }
+ if (_sketchFilter) {
+ _sketchFilter->release();
+ _sketchFilter = 0;
+ }
+}
+
+SketchFilter* SketchFilter::create() {
+ SketchFilter* ret = new (std::nothrow) SketchFilter();
+ if (ret && !ret->init()) {
+ delete ret;
+ ret = 0;
+ }
+
+ return ret;
+}
+
+bool SketchFilter::init() {
+ if (!FilterGroup::init()) {
+ return false;
+ }
+
+ _grayscaleFilter = GrayscaleFilter::create();
+ _sketchFilter = _SketchFilter::create();
+ _grayscaleFilter->addTarget(_sketchFilter);
+ addFilter(_grayscaleFilter);
+
+
+ _edgeStrength = 1.0;
+ registerProperty("edgeStrength", _edgeStrength, "The edge strength of sobel edge detection filter", [this](float& edgeStrength){
+ _sketchFilter->setEdgeStrength(edgeStrength);
+ });
+
+ return true;
+}
+
+_SketchFilter* _SketchFilter::create() {
+ _SketchFilter* ret = new (std::nothrow) _SketchFilter();
+ if (!ret || !ret->init()) {
+ delete ret;
+ ret = 0;
+ }
+
+ return ret;
+}
+
+bool _SketchFilter::init() {
+ if (!initWithFragmentShaderString(kSketchFilterFragmentShaderString)) {
+ return false;
+ }
+ _edgeStrength = 1.0;
+ return true;
+}
+
+void _SketchFilter::setEdgeStrength(float edgeStrength) {
+ _edgeStrength = edgeStrength;
+}
+
+bool _SketchFilter::proceed(bool bUpdateTargets/* = true*/) {
+ float texelWidth = 1.0 / _framebuffer->getWidth();
+ float texelHeight = 1.0 / _framebuffer->getHeight();
+
+ Framebuffer* inputFramebuffer = _inputFramebuffers.begin()->second.frameBuffer;
+ RotationMode inputRotation = _inputFramebuffers.begin()->second.rotationMode;
+ if (rotationSwapsSize(inputRotation)){
+ texelWidth = 1.0 / _framebuffer->getHeight();
+ texelHeight = 1.0 / _framebuffer->getWidth();
+ }
+
+ _filterProgram->setUniformValue("texelWidth", texelWidth);
+ _filterProgram->setUniformValue("texelHeight", texelHeight);
+ _filterProgram->setUniformValue("edgeStrength", _edgeStrength);
+ return NearbySampling3x3Filter::proceed(bUpdateTargets);
+}
+
+
+NS_GI_END
diff --git a/filter/src/main/cpp/effect/SketchFilter.hpp b/filter/src/main/cpp/effect/SketchFilter.hpp
new file mode 100755
index 0000000..71dd0c7
--- /dev/null
+++ b/filter/src/main/cpp/effect/SketchFilter.hpp
@@ -0,0 +1,64 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef SketchFilter_hpp
+#define SketchFilter_hpp
+
+#include "../source/macros.h"
+#include "FilterGroup.hpp"
+#include "GrayscaleFilter.hpp"
+#include "NearbySampling3x3Filter.hpp"
+
+NS_GI_BEGIN
+
+// Sketch filter is just the Sobel edge detection filter with the colors inverted.
+
+class _SketchFilter;
+
+class SketchFilter : public FilterGroup {
+public:
+ static SketchFilter* create();
+ bool init();
+
+protected:
+ SketchFilter();
+ ~SketchFilter();
+
+ GrayscaleFilter* _grayscaleFilter;
+ _SketchFilter* _sketchFilter;
+
+ float _edgeStrength;
+};
+
+class _SketchFilter : public NearbySampling3x3Filter {
+public:
+ static _SketchFilter* create();
+ bool init();
+ virtual bool proceed(bool bUpdateTargets = true) override;
+
+ void setEdgeStrength(float edgeStrength);
+
+protected:
+ _SketchFilter() {};
+
+ float _edgeStrength;
+};
+
+NS_GI_END
+
+#endif /* SketchFilter_hpp */
diff --git a/filter/src/main/cpp/effect/SmoothToonFilter.cpp b/filter/src/main/cpp/effect/SmoothToonFilter.cpp
new file mode 100755
index 0000000..8f8d367
--- /dev/null
+++ b/filter/src/main/cpp/effect/SmoothToonFilter.cpp
@@ -0,0 +1,99 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include "SmoothToonFilter.hpp"
+
+NS_GI_BEGIN
+
+REGISTER_FILTER_CLASS(SmoothToonFilter)
+
+SmoothToonFilter::SmoothToonFilter()
+:_gaussianBlurFilter(0)
+,_toonFilter(0)
+{
+}
+
+SmoothToonFilter::~SmoothToonFilter() {
+ if (_gaussianBlurFilter) {
+ _gaussianBlurFilter->release();
+ _gaussianBlurFilter = 0;
+ }
+
+ if (_toonFilter) {
+ _toonFilter->release();
+ _toonFilter = 0;
+ }
+
+}
+
+SmoothToonFilter* SmoothToonFilter::create() {
+ SmoothToonFilter* ret = new (std::nothrow) SmoothToonFilter();
+ if (ret && !ret->init()) {
+ delete ret;
+ ret = 0;
+ }
+ return ret;
+}
+
+bool SmoothToonFilter::init() {
+ if (!FilterGroup::init()) {
+ return false;
+ }
+ _gaussianBlurFilter = GaussianBlurFilter::create();
+ _toonFilter = ToonFilter::create();
+ _gaussianBlurFilter->addTarget(_toonFilter);
+ addFilter(_gaussianBlurFilter);
+
+
+ _blurRadius = 2.0;
+ setBlurRadius(_blurRadius);
+ registerProperty("blurRadius", _blurRadius, "", [this](int& blurRadius){
+ setBlurRadius(blurRadius);
+ });
+
+ _toonThreshold = 0.2;
+ registerProperty("toonThreshold", _toonThreshold, "The threshold at which to apply the edges", [this](float& toonThreshold){
+ setToonThreshold(toonThreshold);
+ });
+
+ _toonQuantizationLevels = 10.0;
+ registerProperty("toonQuantizationLevels", _toonQuantizationLevels, "The levels of quantization for the posterization of colors within the scene", [this](float& toonQuantizationLevels){
+ setToonQuantizationLevels(toonQuantizationLevels);
+ });
+
+
+ return true;
+}
+
+void SmoothToonFilter::setBlurRadius(int blurRadius) {
+ _blurRadius = blurRadius;
+ _gaussianBlurFilter->setRadius(_blurRadius);
+}
+
+void SmoothToonFilter::setToonThreshold(float toonThreshold) {
+ _toonThreshold = toonThreshold;
+ _toonFilter->setThreshold(_toonThreshold);
+}
+
+void SmoothToonFilter::setToonQuantizationLevels(float toonQuantizationLevels) {
+ _toonQuantizationLevels = toonQuantizationLevels;
+ _toonFilter->setQuantizatinLevels(_toonQuantizationLevels);
+}
+
+
+NS_GI_END
diff --git a/filter/src/main/cpp/effect/SmoothToonFilter.hpp b/filter/src/main/cpp/effect/SmoothToonFilter.hpp
new file mode 100755
index 0000000..34883b9
--- /dev/null
+++ b/filter/src/main/cpp/effect/SmoothToonFilter.hpp
@@ -0,0 +1,55 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef SmoothToonFilter_hpp
+#define SmoothToonFilter_hpp
+
+#include "../source/macros.h"
+#include "FilterGroup.hpp"
+#include "GaussianBlurFilter.hpp"
+#include "ToonFilter.hpp"
+
+NS_GI_BEGIN
+
+class SmoothToonFilter : public FilterGroup {
+public:
+ virtual ~SmoothToonFilter();
+
+ static SmoothToonFilter* create();
+ bool init();
+
+ void setBlurRadius(int blurRadius);
+ void setToonThreshold(float toonThreshold);
+ void setToonQuantizationLevels(float toonQuantizationLevels);
+
+protected:
+ SmoothToonFilter();
+
+private:
+ GaussianBlurFilter* _gaussianBlurFilter;
+ ToonFilter* _toonFilter;
+
+ float _blurRadius;
+ float _toonThreshold;
+ float _toonQuantizationLevels;
+};
+
+
+NS_GI_END
+
+#endif /* SmoothToonFilter_hpp */
diff --git a/filter/src/main/cpp/effect/SobelEdgeDetectionFilter.cpp b/filter/src/main/cpp/effect/SobelEdgeDetectionFilter.cpp
new file mode 100755
index 0000000..1a4edcf
--- /dev/null
+++ b/filter/src/main/cpp/effect/SobelEdgeDetectionFilter.cpp
@@ -0,0 +1,148 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include "SobelEdgeDetectionFilter.hpp"
+
+NS_GI_BEGIN
+
+REGISTER_FILTER_CLASS(SobelEdgeDetectionFilter)
+
+// Code from "Graphics Shaders: Theory and Practice" by M. Bailey and S. Cunningham
+const std::string kSobelEdgeDetectionFragmentShaderString = SHADER_STRING
+(
+ precision mediump float;
+ uniform sampler2D colorMap;
+ uniform float edgeStrength;
+
+ varying vec2 vTexCoord;
+ varying vec2 vLeftTexCoord;
+ varying vec2 vRightTexCoord;
+
+ varying vec2 vTopTexCoord;
+ varying vec2 vTopLeftTexCoord;
+ varying vec2 vTopRightTexCoord;
+
+ varying vec2 vBottomTexCoord;
+ varying vec2 vBottomLeftTexCoord;
+ varying vec2 vBottomRightTexCoord;
+
+ void main()
+ {
+ float bottomLeftIntensity = texture2D(colorMap, vBottomLeftTexCoord).r;
+ float topRightIntensity = texture2D(colorMap, vTopRightTexCoord).r;
+ float topLeftIntensity = texture2D(colorMap, vTopLeftTexCoord).r;
+ float bottomRightIntensity = texture2D(colorMap, vBottomRightTexCoord).r;
+ float leftIntensity = texture2D(colorMap, vLeftTexCoord).r;
+ float rightIntensity = texture2D(colorMap, vRightTexCoord).r;
+ float bottomIntensity = texture2D(colorMap, vBottomTexCoord).r;
+ float topIntensity = texture2D(colorMap, vTopTexCoord).r;
+ float h = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + bottomLeftIntensity + 2.0 * bottomIntensity + bottomRightIntensity;
+ float v = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomRightIntensity + 2.0 * rightIntensity + topRightIntensity;
+
+ float mag = length(vec2(h, v)) * edgeStrength;
+ gl_FragColor = vec4(vec3(mag), 1.0);
+ }
+ );
+
+SobelEdgeDetectionFilter::SobelEdgeDetectionFilter()
+:_grayscaleFilter(0)
+,_sobelEdgeDetectionFilter(0)
+{
+}
+
+SobelEdgeDetectionFilter::~SobelEdgeDetectionFilter() {
+ if (_grayscaleFilter) {
+ _grayscaleFilter->release();
+ _grayscaleFilter = 0;
+ }
+ if (_sobelEdgeDetectionFilter) {
+ _sobelEdgeDetectionFilter->release();
+ _sobelEdgeDetectionFilter = 0;
+ }
+}
+
+SobelEdgeDetectionFilter* SobelEdgeDetectionFilter::create() {
+ SobelEdgeDetectionFilter* ret = new (std::nothrow) SobelEdgeDetectionFilter();
+ if (ret && !ret->init()) {
+ delete ret;
+ ret = 0;
+ }
+
+ return ret;
+}
+
+bool SobelEdgeDetectionFilter::init() {
+ if (!FilterGroup::init()) {
+ return false;
+ }
+
+ _grayscaleFilter = GrayscaleFilter::create();
+ _sobelEdgeDetectionFilter = _SobelEdgeDetectionFilter::create();
+ _grayscaleFilter->addTarget(_sobelEdgeDetectionFilter);
+ addFilter(_grayscaleFilter);
+
+
+ _edgeStrength = 1.0;
+ registerProperty("edgeStrength", _edgeStrength, "The edge strength of sobel edge detection filter", [this](float& edgeStrength){
+ _sobelEdgeDetectionFilter->setEdgeStrength(edgeStrength);
+ });
+
+ return true;
+}
+
+_SobelEdgeDetectionFilter* _SobelEdgeDetectionFilter::create() {
+ _SobelEdgeDetectionFilter* ret = new (std::nothrow) _SobelEdgeDetectionFilter();
+ if (!ret || !ret->init()) {
+ delete ret;
+ ret = 0;
+ }
+
+ return ret;
+}
+
+bool _SobelEdgeDetectionFilter::init() {
+ if (!initWithFragmentShaderString(kSobelEdgeDetectionFragmentShaderString)) {
+ return false;
+ }
+ _edgeStrength = 1.0;
+ return true;
+}
+
+void _SobelEdgeDetectionFilter::setEdgeStrength(float edgeStrength) {
+ _edgeStrength = edgeStrength;
+}
+
+bool _SobelEdgeDetectionFilter::proceed(bool bUpdateTargets/* = true*/) {
+ float texelWidth = 1.0 / _framebuffer->getWidth();
+ float texelHeight = 1.0 / _framebuffer->getHeight();
+
+ Framebuffer* inputFramebuffer = _inputFramebuffers.begin()->second.frameBuffer;
+ RotationMode inputRotation = _inputFramebuffers.begin()->second.rotationMode;
+ if (rotationSwapsSize(inputRotation)){
+ texelWidth = 1.0 / _framebuffer->getHeight();
+ texelHeight = 1.0 / _framebuffer->getWidth();
+ }
+
+ _filterProgram->setUniformValue("texelWidth", texelWidth);
+ _filterProgram->setUniformValue("texelHeight", texelHeight);
+ _filterProgram->setUniformValue("edgeStrength", _edgeStrength);
+ return NearbySampling3x3Filter::proceed(bUpdateTargets);
+}
+
+
+NS_GI_END
diff --git a/filter/src/main/cpp/effect/SobelEdgeDetectionFilter.hpp b/filter/src/main/cpp/effect/SobelEdgeDetectionFilter.hpp
new file mode 100755
index 0000000..4a71343
--- /dev/null
+++ b/filter/src/main/cpp/effect/SobelEdgeDetectionFilter.hpp
@@ -0,0 +1,62 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef SobelEdgeDetectionFilter_hpp
+#define SobelEdgeDetectionFilter_hpp
+
+#include "../source/macros.h"
+#include "FilterGroup.hpp"
+#include "GrayscaleFilter.hpp"
+#include "NearbySampling3x3Filter.hpp"
+
+NS_GI_BEGIN
+
+class _SobelEdgeDetectionFilter;
+
+class SobelEdgeDetectionFilter : public FilterGroup {
+public:
+ static SobelEdgeDetectionFilter* create();
+ bool init();
+
+protected:
+ SobelEdgeDetectionFilter();
+ ~SobelEdgeDetectionFilter();
+
+ GrayscaleFilter* _grayscaleFilter;
+ _SobelEdgeDetectionFilter* _sobelEdgeDetectionFilter;
+
+ float _edgeStrength;
+};
+
+class _SobelEdgeDetectionFilter : public NearbySampling3x3Filter {
+public:
+ static _SobelEdgeDetectionFilter* create();
+ bool init();
+ virtual bool proceed(bool bUpdateTargets = true) override;
+
+ void setEdgeStrength(float edgeStrength);
+
+protected:
+ _SobelEdgeDetectionFilter() {};
+
+ float _edgeStrength;
+};
+
+NS_GI_END
+
+#endif /* SobelEdgeDetectionFilter_hpp */
diff --git a/filter/src/main/cpp/effect/SphereRefractionFilter.cpp b/filter/src/main/cpp/effect/SphereRefractionFilter.cpp
new file mode 100755
index 0000000..b3c1033
--- /dev/null
+++ b/filter/src/main/cpp/effect/SphereRefractionFilter.cpp
@@ -0,0 +1,119 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include "SphereRefractionFilter.hpp"
+
+USING_NS_GI
+
+REGISTER_FILTER_CLASS(SphereRefractionFilter)
+
+const std::string kSphereRefractionShaderString = SHADER_STRING
+(
+
+ uniform sampler2D colorMap;
+ uniform highp vec2 center;
+ uniform highp float radius;
+ uniform highp float aspectRatio;
+ uniform highp float refractiveIndex;
+
+ varying highp vec2 vTexCoord;
+
+ void main()
+ {
+ highp vec2 textureCoordinateToUse = vec2(vTexCoord.x, (vTexCoord.y * aspectRatio + 0.5 - 0.5 * aspectRatio));
+ highp float distanceFromCenter = distance(center, textureCoordinateToUse);
+ lowp float checkForPresenceWithinSphere = step(distanceFromCenter, radius);
+
+ distanceFromCenter = distanceFromCenter / radius;
+
+ highp float normalizedDepth = radius * sqrt(1.0 - distanceFromCenter * distanceFromCenter);
+ highp vec3 sphereNormal = normalize(vec3(textureCoordinateToUse - center, normalizedDepth));
+
+ highp vec3 refractedVector = refract(vec3(0.0, 0.0, -1.0), sphereNormal, refractiveIndex);
+
+ gl_FragColor = texture2D(colorMap, (refractedVector.xy + 1.0) * 0.5) * checkForPresenceWithinSphere;
+ }
+
+);
+
+
+SphereRefractionFilter* SphereRefractionFilter::create() {
+ SphereRefractionFilter* ret = new (std::nothrow) SphereRefractionFilter();
+ if (ret && !ret->init()) {
+ delete ret;
+ ret = 0;
+ }
+ return ret;
+}
+
+bool SphereRefractionFilter::init() {
+ if (!initWithFragmentShaderString(kSphereRefractionShaderString)) return false;
+
+
+ setPositionX(0.5);
+ registerProperty("positionX", _position.x, "The position of x about which to apply the distortion, with a default of 0.5", [this](float& positionX){
+ setPositionX(positionX);
+ });
+
+ setPositionY(0.5);
+ registerProperty("positionY", _position.y, "The position of y about which to apply the distortion, with a default of 0.5", [this](float& positionY){
+ setPositionY(positionY);
+ });
+
+ setRadius(0.25);
+ registerProperty("radius", _radius, "The radius of the distortion, ranging from 0.0 to 1.0, with a default of 0.25", [this](float& radius){
+ setRadius(radius);
+ });
+
+ setRefractiveIndex(0.71);
+ registerProperty("refractiveIndex", _refractiveIndex, "The index of refraction for the sphere, with a default of 0.71", [this](float& refractiveIndex){
+ setRefractiveIndex(refractiveIndex);
+ });
+
+ return true;
+}
+
+bool SphereRefractionFilter::proceed(bool bUpdateTargets/* = true*/) {
+ _filterProgram->setUniformValue("center", _position);
+ _filterProgram->setUniformValue("radius", _radius);
+ _filterProgram->setUniformValue("refractiveIndex", _refractiveIndex);
+
+ float aspectRatio = 1.0;
+ Framebuffer* firstInputFramebuffer = _inputFramebuffers.begin()->second.frameBuffer;
+ aspectRatio = firstInputFramebuffer->getHeight() / (float)(firstInputFramebuffer->getWidth());
+ _filterProgram->setUniformValue("aspectRatio", aspectRatio);
+
+ return Filter::proceed(bUpdateTargets);
+}
+
+void SphereRefractionFilter::setPositionX(float x) {
+ _position.x = x;
+}
+
+void SphereRefractionFilter::setPositionY(float y) {
+ _position.y = y;
+}
+
+void SphereRefractionFilter::setRadius(float radius) {
+ _radius = radius;
+}
+
+void SphereRefractionFilter::setRefractiveIndex(float refractiveIndex) {
+ _refractiveIndex = refractiveIndex;
+}
+
diff --git a/filter/src/main/cpp/effect/SphereRefractionFilter.hpp b/filter/src/main/cpp/effect/SphereRefractionFilter.hpp
new file mode 100755
index 0000000..a31c49a
--- /dev/null
+++ b/filter/src/main/cpp/effect/SphereRefractionFilter.hpp
@@ -0,0 +1,54 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef SphereRefractionFilter_hpp
+#define SphereRefractionFilter_hpp
+
+#include "../source/macros.h"
+#include "Filter.hpp"
+
+NS_GI_BEGIN
+
+class SphereRefractionFilter : public Filter {
+public:
+ static SphereRefractionFilter* create();
+ bool init();
+ virtual bool proceed(bool bUpdateTargets = true) override;
+
+ void setPositionX(float x);
+ void setPositionY(float y);
+ void setRadius(float radius);
+ void setRefractiveIndex(float refractiveIndex);
+
+protected:
+ SphereRefractionFilter() {};
+
+ // The position about which to apply the distortion, with a default of (0.5, 0.5)
+ Vector2 _position;
+
+ // The radius of the distortion, ranging from 0.0 to 1.0, with a default of 0.25
+ float _radius;
+
+ // The index of refraction for the sphere, with a default of 0.71
+ float _refractiveIndex;
+
+};
+
+NS_GI_END
+
+#endif /* SphereRefractionFilter_hpp */
diff --git a/filter/src/main/cpp/effect/ToonFilter.cpp b/filter/src/main/cpp/effect/ToonFilter.cpp
new file mode 100755
index 0000000..8257ee8
--- /dev/null
+++ b/filter/src/main/cpp/effect/ToonFilter.cpp
@@ -0,0 +1,107 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include "ToonFilter.hpp"
+
+USING_NS_GI
+
+REGISTER_FILTER_CLASS(ToonFilter)
+
+const std::string kToonFragmentShaderString = SHADER_STRING
+(
+ precision mediump float;
+ uniform sampler2D colorMap;
+ uniform float threshold;
+ uniform float quantizationLevels;
+
+ varying vec2 vTexCoord;
+ varying vec2 vLeftTexCoord;
+ varying vec2 vRightTexCoord;
+
+ varying vec2 vTopTexCoord;
+ varying vec2 vTopLeftTexCoord;
+ varying vec2 vTopRightTexCoord;
+
+ varying vec2 vBottomTexCoord;
+ varying vec2 vBottomLeftTexCoord;
+ varying vec2 vBottomRightTexCoord;
+
+ void main()
+ {
+ float bottomLeftIntensity = texture2D(colorMap, vBottomLeftTexCoord).r;
+ float topRightIntensity = texture2D(colorMap, vTopRightTexCoord).r;
+ float topLeftIntensity = texture2D(colorMap, vTopLeftTexCoord).r;
+ float bottomRightIntensity = texture2D(colorMap, vBottomRightTexCoord).r;
+ float leftIntensity = texture2D(colorMap, vLeftTexCoord).r;
+ float rightIntensity = texture2D(colorMap, vRightTexCoord).r;
+ float bottomIntensity = texture2D(colorMap, vBottomTexCoord).r;
+ float topIntensity = texture2D(colorMap, vTopTexCoord).r;
+ float h = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + bottomLeftIntensity + 2.0 * bottomIntensity + bottomRightIntensity;
+ float v = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomRightIntensity + 2.0 * rightIntensity + topRightIntensity;
+
+ float mag = length(vec2(h, v));
+
+ vec4 color = texture2D(colorMap, vTexCoord);
+ vec3 posterizedImageColor = (floor(color.rgb * quantizationLevels) + 0.5) / quantizationLevels;
+
+ float thresholdTest = 1.0 - step(threshold, mag);
+
+ gl_FragColor = vec4(posterizedImageColor * thresholdTest, color.a);
+ }
+ );
+
+
+ToonFilter* ToonFilter::create() {
+ ToonFilter* ret = new (std::nothrow) ToonFilter();
+ if (ret && !ret->init()) {
+ delete ret;
+ ret = 0;
+ }
+ return ret;
+}
+
+bool ToonFilter::init() {
+ if (!initWithFragmentShaderString(kToonFragmentShaderString)) return false;
+
+ _threshold = 0.2;
+ registerProperty("threshold", _threshold, "The threshold at which to apply the edges", [this](float& threshold){
+ setThreshold(threshold);
+ });
+
+ _quantizationLevels = 10.0;
+ registerProperty("quantizationLevels", _quantizationLevels, "The levels of quantization for the posterization of colors within the scene", [this](float& quantizationLevels){
+ setQuantizatinLevels(quantizationLevels);
+ });
+
+ return true;
+}
+
+void ToonFilter::setThreshold(float threshold) {
+ _threshold = threshold;
+}
+
+void ToonFilter::setQuantizatinLevels(float quantizationLevels) {
+ _quantizationLevels = quantizationLevels;
+}
+
+bool ToonFilter::proceed(bool bUpdateTargets/* = true*/) {
+ _filterProgram->setUniformValue("threshold", _threshold);
+ _filterProgram->setUniformValue("quantizationLevels", _quantizationLevels);
+ return NearbySampling3x3Filter::proceed(bUpdateTargets);
+}
+
diff --git a/filter/src/main/cpp/effect/ToonFilter.hpp b/filter/src/main/cpp/effect/ToonFilter.hpp
new file mode 100755
index 0000000..3523019
--- /dev/null
+++ b/filter/src/main/cpp/effect/ToonFilter.hpp
@@ -0,0 +1,45 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef ToonFilter_hpp
+#define ToonFilter_hpp
+
+#include "../source/macros.h"
+#include "NearbySampling3x3Filter.hpp"
+
+NS_GI_BEGIN
+
+class ToonFilter : public NearbySampling3x3Filter {
+public:
+ static ToonFilter* create();
+ bool init();
+ virtual bool proceed(bool bUpdateTargets = true) override;
+
+ void setThreshold(float threshold);
+ void setQuantizatinLevels(float quantizationLevels);
+
+protected:
+ ToonFilter() {};
+
+ float _threshold;
+ float _quantizationLevels;
+};
+
+NS_GI_END
+
+#endif /* ToonFilter_hpp */
diff --git a/filter/src/main/cpp/effect/WeakPixelInclusionFilter.cpp b/filter/src/main/cpp/effect/WeakPixelInclusionFilter.cpp
new file mode 100755
index 0000000..9f4e7b0
--- /dev/null
+++ b/filter/src/main/cpp/effect/WeakPixelInclusionFilter.cpp
@@ -0,0 +1,80 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include "WeakPixelInclusionFilter.hpp"
+
+NS_GI_BEGIN
+
+REGISTER_FILTER_CLASS(WeakPixelInclusionFilter)
+
+const std::string kWeakPixelInclusionFragmentShaderString = SHADER_STRING
+(
+ precision mediump float;
+ uniform sampler2D colorMap;
+
+ varying vec2 vTexCoord;
+ varying vec2 vLeftTexCoord;
+ varying vec2 vRightTexCoord;
+
+ varying vec2 vTopTexCoord;
+ varying vec2 vTopLeftTexCoord;
+ varying vec2 vTopRightTexCoord;
+
+ varying vec2 vBottomTexCoord;
+ varying vec2 vBottomLeftTexCoord;
+ varying vec2 vBottomRightTexCoord;
+
+ void main()
+ {
+ float bottomLeftIntensity = texture2D(colorMap, vBottomLeftTexCoord).r;
+ float topRightIntensity = texture2D(colorMap, vTopRightTexCoord).r;
+ float topLeftIntensity = texture2D(colorMap, vTopLeftTexCoord).r;
+ float bottomRightIntensity = texture2D(colorMap, vBottomRightTexCoord).r;
+ float leftIntensity = texture2D(colorMap, vLeftTexCoord).r;
+ float rightIntensity = texture2D(colorMap, vRightTexCoord).r;
+ float bottomIntensity = texture2D(colorMap, vBottomTexCoord).r;
+ float topIntensity = texture2D(colorMap, vTopTexCoord).r;
+ float centerIntensity = texture2D(colorMap, vTexCoord).r;
+
+ float pixelIntensitySum = bottomLeftIntensity + topRightIntensity + topLeftIntensity + bottomRightIntensity + leftIntensity + rightIntensity + bottomIntensity + topIntensity + centerIntensity;
+ float sumTest = step(1.5, pixelIntensitySum);
+ float pixelTest = step(0.01, centerIntensity);
+
+ gl_FragColor = vec4(vec3(sumTest * pixelTest), 1.0);
+ }
+ );
+
+
+WeakPixelInclusionFilter* WeakPixelInclusionFilter::create() {
+ WeakPixelInclusionFilter* ret = new (std::nothrow) WeakPixelInclusionFilter();
+ if (ret && !ret->init()) {
+ delete ret;
+ ret = 0;
+ }
+ return ret;
+}
+
+bool WeakPixelInclusionFilter::init() {
+ if (initWithFragmentShaderString(kWeakPixelInclusionFragmentShaderString)) {
+ return true;
+ }
+ return false;
+}
+
+
+NS_GI_END
diff --git a/filter/src/main/cpp/effect/WeakPixelInclusionFilter.hpp b/filter/src/main/cpp/effect/WeakPixelInclusionFilter.hpp
new file mode 100755
index 0000000..6321af6
--- /dev/null
+++ b/filter/src/main/cpp/effect/WeakPixelInclusionFilter.hpp
@@ -0,0 +1,40 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef WeakPixelInclusionFilter_hpp
+#define WeakPixelInclusionFilter_hpp
+
+#include "../source/macros.h"
+#include "NearbySampling3x3Filter.hpp"
+
+NS_GI_BEGIN
+
+class WeakPixelInclusionFilter : public NearbySampling3x3Filter {
+public:
+ static WeakPixelInclusionFilter* create();
+ bool init();
+
+
+protected:
+
+ WeakPixelInclusionFilter() {};
+};
+
+NS_GI_END
+
+#endif /* WeakPixelInclusionFilter_hpp */
diff --git a/filter/src/main/cpp/effect/WhiteBalanceFilter.cpp b/filter/src/main/cpp/effect/WhiteBalanceFilter.cpp
new file mode 100755
index 0000000..a2358c3
--- /dev/null
+++ b/filter/src/main/cpp/effect/WhiteBalanceFilter.cpp
@@ -0,0 +1,90 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#include "WhiteBalanceFilter.hpp"
+
+USING_NS_GI
+
+REGISTER_FILTER_CLASS(WhiteBalanceFilter)
+
+const std::string kWhiteBalanceFragmentShaderString = SHADER_STRING
+(
+ uniform sampler2D colorMap;
+ uniform lowp float temperature;
+ uniform lowp float tint;
+ varying highp vec2 vTexCoord;
+ const lowp vec3 warmFilter = vec3(0.93, 0.54, 0.0);
+ const mediump mat3 RGBtoYIQ = mat3(0.299, 0.587, 0.114, 0.596, -0.274, -0.322, 0.212, -0.523, 0.311);
+ const mediump mat3 YIQtoRGB = mat3(1.0, 0.956, 0.621, 1.0, -0.272, -0.647, 1.0, -1.105, 1.702);
+
+ void main()
+ {
+ lowp vec4 color = texture2D(colorMap, vTexCoord);
+ mediump vec3 yiq = RGBtoYIQ * color.rgb; //adjusting tint
+ yiq.b = clamp(yiq.b + tint * 0.5226 * 0.1, -0.5226, 0.5226);
+ lowp vec3 rgb = YIQtoRGB * yiq;
+ lowp vec3 processed = vec3(
+ (rgb.r < 0.5 ? (2.0 * rgb.r * warmFilter.r) : (1.0 - 2.0 * (1.0 - rgb.r) * (1.0 - warmFilter.r))), //adjusting temperature
+ (rgb.g < 0.5 ? (2.0 * rgb.g * warmFilter.g) : (1.0 - 2.0 * (1.0 - rgb.g) * (1.0 - warmFilter.g))),
+ (rgb.b < 0.5 ? (2.0 * rgb.b * warmFilter.b) : (1.0 - 2.0 * (1.0 - rgb.b) * (1.0 - warmFilter.b))));
+
+ gl_FragColor = vec4(mix(rgb, processed, temperature), color.a);
+
+ }
+);
+
+
+WhiteBalanceFilter* WhiteBalanceFilter::create() {
+ WhiteBalanceFilter* ret = new (std::nothrow) WhiteBalanceFilter();
+ if (ret && !ret->init()) {
+ delete ret;
+ ret = 0;
+ }
+ return ret;
+}
+
+bool WhiteBalanceFilter::init() {
+ if (!initWithFragmentShaderString(kWhiteBalanceFragmentShaderString)) return false;
+
+ setTemperature(5000.0);
+ registerProperty("temperature", 5000.0, "Adjustment of color temperature (in degrees Kelvin) in terms of what an image was effectively shot in. This means higher Kelvin values will warm the image, while lower values will cool it.", [this](float& temperature){
+ setTemperature(temperature);
+ });
+
+ setTint(0.0);
+ registerProperty("tint", _tint, "adjust tint to compensate", [this](float& tint){
+ setTint(tint);
+ });
+
+ return true;
+}
+
+void WhiteBalanceFilter::setTemperature(float temperature) {
+ _temperature = temperature < 5000 ? 0.0004 * (temperature - 5000.0) : 0.00006 * (temperature - 5000.0);
+}
+
+void WhiteBalanceFilter::setTint(float tint) {
+ _tint = tint / 100.0;
+}
+
+bool WhiteBalanceFilter::proceed(bool bUpdateTargets/* = true*/) {
+ _filterProgram->setUniformValue("temperature", _temperature);
+ _filterProgram->setUniformValue("tint", _tint);
+ return Filter::proceed(bUpdateTargets);
+}
+
diff --git a/filter/src/main/cpp/effect/WhiteBalanceFilter.hpp b/filter/src/main/cpp/effect/WhiteBalanceFilter.hpp
new file mode 100755
index 0000000..12306dd
--- /dev/null
+++ b/filter/src/main/cpp/effect/WhiteBalanceFilter.hpp
@@ -0,0 +1,45 @@
+/*
+ * GPUImage-x
+ *
+ * Copyright (C) 2017 Yijin Wang, Yiqian Wang
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * 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.
+ */
+
+#ifndef WhiteBalanceFilter_hpp
+#define WhiteBalanceFilter_hpp
+
+#include "../source/macros.h"
+#include "Filter.hpp"
+
+NS_GI_BEGIN
+
+class WhiteBalanceFilter : public Filter {
+public:
+ static WhiteBalanceFilter* create();
+ bool init();
+ virtual bool proceed(bool bUpdateTargets = true) override;
+
+ void setTemperature(float temperature);
+ void setTint(float tint);
+
+protected:
+ WhiteBalanceFilter() {};
+
+ float _temperature;
+ float _tint;
+};
+
+NS_GI_END
+
+#endif /* WhiteBalanceFilter_hpp */
diff --git a/filter/src/main/cpp/egl/EGLCore.cpp b/filter/src/main/cpp/egl/EGLCore.cpp
new file mode 100644
index 0000000..37cda49
--- /dev/null
+++ b/filter/src/main/cpp/egl/EGLCore.cpp
@@ -0,0 +1,227 @@
+#include
+#include "EGLCore.h"
+#include
+
+
+#define LOG_TAG "EGLCore"
+#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
+#define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
+
+/**
+ * EGL是介于诸如OpenGL 或OpenVG的Khronos渲染API与底层本地平台窗口系统的接口。它被用于处理图形管理、表面/缓冲捆绑、渲染同步及支援使用其他Khronos API进行的高效、加速、混合模式2D和3D渲染。
+ * cangwang 2018.12.1
+ */
+EGLCore::EGLCore():mDisplay(EGL_NO_DISPLAY),mSurface(EGL_NO_SURFACE),mContext(EGL_NO_CONTEXT) {
+
+
+}
+
+EGLCore::~EGLCore() {
+ mDisplay = EGL_NO_DISPLAY;
+ mSurface = EGL_NO_SURFACE;
+ mContext = EGL_NO_CONTEXT;
+}
+
+GLboolean EGLCore::buildContext(ANativeWindow *window, EGLContext context) {
+ //与本地窗口通信
+ mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ if (mDisplay == EGL_NO_DISPLAY){
+ ALOGE("eglGetDisplay failed: %d",eglGetError());
+ return GL_FALSE;
+ }
+
+ GLint majorVersion;
+ GLint minorVersion;
+ //获取支持最低和最高版本
+ if (!eglInitialize(mDisplay,&majorVersion,&minorVersion)){
+ ALOGE("eglInitialize failed: %d",eglGetError());
+ return GL_FALSE;
+ }
+
+ EGLConfig config;
+ EGLint numConfigs = 0;
+ //颜色使用565,读写类型需要egl扩展
+ EGLint attribList[] = {
+ EGL_RED_SIZE,5, //指定RGB中的R大小(bits)
+ EGL_GREEN_SIZE,6, //指定G大小
+ EGL_BLUE_SIZE,5, //指定B大小
+ EGL_RENDERABLE_TYPE,EGL_OPENGL_ES3_BIT_KHR, //渲染类型,为相机扩展类型
+// EGL_SURFACE_TYPE,EGL_WINDOW_BIT, //绘图类型,
+ EGL_NONE
+ };
+
+ //让EGL推荐匹配的EGLConfig
+ if(!eglChooseConfig(mDisplay,attribList,&config,1,&numConfigs)){
+ ALOGE("eglChooseConfig failed: %d",eglGetError());
+ return GL_FALSE;
+ }
+
+ //找不到匹配的
+ if (numConfigs <1){
+ ALOGE("eglChooseConfig get config number less than one");
+ return GL_FALSE;
+ }
+
+ //创建渲染上下文
+ //只使用opengles3
+ GLint contextAttrib[] = {EGL_CONTEXT_CLIENT_VERSION,3,EGL_NONE};
+ // EGL_NO_CONTEXT表示不向其它的context共享资源
+ if(context){
+ mContext = context;
+ } else {
+ mContext = eglCreateContext(mDisplay, config, EGL_NO_CONTEXT, contextAttrib);
+ if (mContext == EGL_NO_CONTEXT){
+ ALOGE("eglCreateContext failed: %d",eglGetError());
+ return GL_FALSE;
+ }
+ }
+
+ EGLint format = 0;
+ if (!eglGetConfigAttrib(mDisplay,config,EGL_NATIVE_VISUAL_ID,&format)){
+ ALOGE("eglGetConfigAttrib failed: %d",eglGetError());
+ return GL_FALSE;
+ }
+ ANativeWindow_setBuffersGeometry(window,0,0,format);
+
+ //创建On-Screen 渲染区域
+ mSurface = eglCreateWindowSurface(mDisplay,config,window,0);
+ if (mSurface == EGL_NO_SURFACE){
+ ALOGE("eglCreateWindowSurface failed: %d",eglGetError());
+ return GL_FALSE;
+ }
+
+ //把EGLContext和EGLSurface关联起来,单缓冲只使用了一个surface
+ if (!eglMakeCurrent(mDisplay,mSurface,mSurface,mContext)){
+ ALOGE("eglMakeCurrent failed: %d",eglGetError());
+ return GL_FALSE;
+ }
+
+ // 获取eglPresentationTimeANDROID方法的地址
+// eglPresentationTimeANDROID = (EGL_PRESENTATION_TIME_ANDROIDPROC)
+// eglGetProcAddress("eglPresentationTimeANDROID");
+// if (!eglPresentationTimeANDROID) {
+// ALOGE("eglPresentationTimeANDROID is not available!");
+// }
+
+ ALOGD("buildVideoContext Succeed");
+ return GL_TRUE;
+}
+
+GLboolean EGLCore::buildVideoContext(ANativeWindow *window, EGLContext context) {
+ //与本地窗口通信
+ mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ if (mDisplay == EGL_NO_DISPLAY){
+ ALOGE("eglGetDisplay failed: %d",eglGetError());
+ return GL_FALSE;
+ }
+
+ GLint majorVersion;
+ GLint minorVersion;
+ //获取支持最低和最高版本
+ if (!eglInitialize(mDisplay,&majorVersion,&minorVersion)){
+ ALOGE("eglInitialize failed: %d",eglGetError());
+ return GL_FALSE;
+ }
+
+ EGLConfig config;
+ EGLint numConfigs = 0;
+ //颜色使用565,读写类型需要egl扩展
+ EGLint attribList[] = {
+ EGL_RED_SIZE,5, //指定RGB中的R大小(bits)
+ EGL_GREEN_SIZE,6, //指定G大小
+ EGL_BLUE_SIZE,5, //指定B大小
+ EGL_RENDERABLE_TYPE,EGL_OPENGL_ES3_BIT_KHR, //渲染类型,为相机扩展类型
+// EGL_SURFACE_TYPE,EGL_WINDOW_BIT, //绘图类型,
+ EGL_RECORDABLE_ANDROID,EGL_ANDROID_recordable,
+ EGL_NONE
+ };
+
+ //让EGL推荐匹配的EGLConfig
+ if(!eglChooseConfig(mDisplay,attribList,&config,1,&numConfigs)){
+ ALOGE("eglChooseConfig failed: %d",eglGetError());
+ return GL_FALSE;
+ }
+
+ //找不到匹配的
+ if (numConfigs <1){
+ ALOGE("eglChooseConfig get config number less than one");
+ return GL_FALSE;
+ }
+
+ //创建渲染上下文
+ //只使用opengles3
+ GLint contextAttrib[] = {EGL_CONTEXT_CLIENT_VERSION,3,EGL_NONE};
+ // EGL_NO_CONTEXT表示不向其它的context共享资源
+ mContext = eglCreateContext(mDisplay, config, context, contextAttrib);
+ if (mContext == EGL_NO_CONTEXT){
+ ALOGE("eglCreateContext failed: %d",eglGetError());
+ return GL_FALSE;
+ }
+
+// if(!eglMakeCurrent(mDisplay,EGL_NO_SURFACE,EGL_NO_SURFACE,EGL_NO_CONTEXT)){
+// ALOGE("eglMakeCurrent reset failed: %d",eglGetError());
+// return GL_FALSE;
+// }
+
+ EGLint format = 0;
+ if (!eglGetConfigAttrib(mDisplay,config,EGL_NATIVE_VISUAL_ID,&format)){
+ ALOGE("eglGetConfigAttrib failed: %d",eglGetError());
+ return GL_FALSE;
+ }
+ ANativeWindow_setBuffersGeometry(window,0,0,format);
+
+ //创建On-Screen 渲染区域
+ mSurface = eglCreateWindowSurface(mDisplay,config,window,0);
+ if (mSurface == EGL_NO_SURFACE){
+ ALOGE("eglCreateWindowSurface failed: %d",eglGetError());
+ return GL_FALSE;
+ }
+
+ //把EGLContext和EGLSurface关联起来,单缓冲只使用了一个surface
+ if (!eglMakeCurrent(mDisplay,mSurface,mSurface,mContext)){
+ ALOGE("eglMakeCurrent failed: %d",eglGetError());
+ return GL_FALSE;
+ }
+
+ // 获取eglPresentationTimeANDROID方法的地址
+ eglPresentationTimeANDROID = (EGL_PRESENTATION_TIME_ANDROIDPROC) eglGetProcAddress("eglPresentationTimeANDROID");
+ if (!eglPresentationTimeANDROID) {
+ ALOGE("eglPresentationTimeANDROID is not available!");
+ }
+
+ ALOGD("buildVideoContext Succeed");
+ return GL_TRUE;
+}
+
+/**
+ * 设置显示时间戳pts
+ * @param nsecs
+ */
+void EGLCore::setPresentationTime(uint64_t nsecs) {
+ eglPresentationTimeANDROID(mDisplay,mSurface,nsecs);
+}
+
+EGLContext EGLCore::getCurrent() {
+ //不能使用eglGetCurrentContext,会返回为空
+ return mContext;
+}
+
+/**
+ * 现在只使用单缓冲绘制
+ */
+void EGLCore::swapBuffer() {
+ //双缓冲绘图,原来是检测出前台display和后台缓冲的差别的dirty区域,然后再区域替换buffer
+ //1)首先计算非dirty区域,然后将非dirty区域数据从上一个buffer拷贝到当前buffer;
+ //2)完成buffer内容的填充,然后将previousBuffer指向buffer,同时queue buffer。
+ //3)Dequeue一块新的buffer,并等待fence。如果等待超时,就将buffer cancel掉。
+ //4)按需重新计算buffer
+ //5)Lock buffer,这样就实现page flip,也就是swapbuffer
+ if (mDisplay!=EGL_NO_DISPLAY && mSurface!= EGL_NO_SURFACE)
+ eglSwapBuffers(mDisplay,mSurface);
+}
+
+void EGLCore::release() {
+ eglDestroySurface(mDisplay,mSurface);
+ eglMakeCurrent(mDisplay,EGL_NO_SURFACE,EGL_NO_SURFACE,EGL_NO_CONTEXT);
+ eglDestroyContext(mDisplay,mContext);
+}
\ No newline at end of file
diff --git a/filter/src/main/cpp/egl/EGLCore.h b/filter/src/main/cpp/egl/EGLCore.h
new file mode 100644
index 0000000..cae5c31
--- /dev/null
+++ b/filter/src/main/cpp/egl/EGLCore.h
@@ -0,0 +1,40 @@
+#include
+#include
+#include
+#include
+
+#ifndef _EGLCore
+#define _EGLCore
+
+/**
+ * cangwang 2018.12.1
+ */
+typedef EGLBoolean (EGLAPIENTRYP EGL_PRESENTATION_TIME_ANDROIDPROC)(EGLDisplay display, EGLSurface surface, khronos_stime_nanoseconds_t time);
+ class EGLCore{
+public:
+ EGLCore();
+
+ ~EGLCore();
+
+ GLboolean buildContext(ANativeWindow *window,EGLContext context);
+ GLboolean buildVideoContext(ANativeWindow *window, EGLContext context);
+
+ EGLContext getCurrent();
+
+ void setPresentationTime(uint64_t nsecs);
+
+ void swapBuffer();
+
+ void release();
+
+ EGLContext mContext;
+
+protected:
+
+private:
+ EGLDisplay mDisplay;
+ EGLSurface mSurface;
+ EGL_PRESENTATION_TIME_ANDROIDPROC eglPresentationTimeANDROID = NULL;
+};
+
+#endif
diff --git a/app/src/main/cpp/egl/GLBase.h b/filter/src/main/cpp/egl/GLBase.h
similarity index 100%
rename from app/src/main/cpp/egl/GLBase.h
rename to filter/src/main/cpp/egl/GLBase.h
diff --git a/app/src/main/cpp/filter/MagicFilterFactory.cpp b/filter/src/main/cpp/filter/MagicFilterFactory.cpp
similarity index 65%
rename from app/src/main/cpp/filter/MagicFilterFactory.cpp
rename to filter/src/main/cpp/filter/MagicFilterFactory.cpp
index 82a8a2a..b735920 100644
--- a/app/src/main/cpp/filter/MagicFilterFactory.cpp
+++ b/filter/src/main/cpp/filter/MagicFilterFactory.cpp
@@ -1,53 +1,54 @@
#include "MagicFilterFactory.h"
-#include "src/main/cpp/filter/advanced/MagicAmaroFilter.h"
-#include "src/main/cpp/filter/advanced/MagicAntiqueFilter.h"
-#include "src/main/cpp/filter/advanced/MagicBlackCatFilter.h"
-#include "src/main/cpp/filter/advanced/MagicBrannanFilter.h"
-#include "src/main/cpp/filter/advanced/MagicBrooklynFilter.h"
-#include "src/main/cpp/filter/advanced/MagicCalmFilter.h"
-#include "src/main/cpp/filter/advanced/MagicCoolFilter.h"
-#include "src/main/cpp/filter/advanced/MagicCrayonFilter.h"
-#include "src/main/cpp/filter/advanced/MagicEarlyBirdFilter.h"
-#include "src/main/cpp/filter/advanced/MagicEmeraldFilter.h"
-#include "src/main/cpp/filter/advanced/MagicEvergreenFilter.h"
-#include "src/main/cpp/filter/advanced/MagicFreudFilter.h"
-#include "src/main/cpp/filter/advanced/MagicFairytableFilter.h"
-#include "src/main/cpp/filter/advanced/MagicHealthyFilter.h"
-#include "src/main/cpp/filter/advanced/MagicHefeFilter.h"
-#include "src/main/cpp/filter/advanced/MagicHudsonFilter.h"
-#include "src/main/cpp/filter/advanced/MagicInkwellFilter.h"
-#include "src/main/cpp/filter/advanced/MagicKevinFilter.h"
-#include "src/main/cpp/filter/advanced/MagicLatteFilter.h"
-#include "src/main/cpp/filter/advanced/MagicLomoFilter.h"
-#include "src/main/cpp/filter/advanced/MagicN1977Filter.h"
-#include "src/main/cpp/filter/advanced/MagicNashvilleFilter.h"
-#include "src/main/cpp/filter/advanced/MagicNostalgiaFilter.h"
-#include
-#include "src/main/cpp/filter/advanced/MagicPixarFilter.h"
-#include "src/main/cpp/filter/advanced/MagicRiseFilter.h"
-#include "src/main/cpp/filter/advanced/MagicRomanceFilter.h"
-#include "src/main/cpp/filter/advanced/MagicSakuraFilter.h"
-#include "src/main/cpp/filter/advanced/MagicSierraFilter.h"
-#include "src/main/cpp/filter/advanced/MagicSketchFilter.h"
-#include "src/main/cpp/filter/advanced/MagicSkinWhiteFilter.h"
-#include "src/main/cpp/filter/advanced/MagicSunriseFilter.h"
-#include "src/main/cpp/filter/advanced/MagicSunsetFilter.h"
-#include "src/main/cpp/filter/advanced/MagicSutroFilter.h"
-#include "src/main/cpp/filter/advanced/MagicSweetsFilter.h"
-#include "src/main/cpp/filter/advanced/MagicTenderFilter.h"
-#include "src/main/cpp/filter/advanced/MagicToasterFilter.h"
-#include "src/main/cpp/filter/advanced/MagicValenciaFilter.h"
-#include "src/main/cpp/filter/advanced/MagicWaldenFilter.h"
-#include "src/main/cpp/filter/advanced/MagicWarmFilter.h"
-#include "src/main/cpp/filter/advanced/MagicWhiteCatFilter.h"
-#include "src/main/cpp/filter/advanced/MagicXproIIFilter.h"
-#include "src/main/cpp/filter/douyin/MagicSoulOutFilter.h"
-#include "src/main/cpp/filter/douyin/MagicGlitchFilter.h"
-#include "src/main/cpp/filter/douyin/MagicScaleFilter.h"
-#include "src/main/cpp/filter/douyin/MagicShineWhiteFilter.h"
-#include "src/main/cpp/filter/douyin/MagicShakeEffectFilter.h"
-#include "src/main/cpp/filter/douyin/MagicVerigoFilter.h"
-#include "src/main/cpp/utils/OpenglUtils.h"
+#include "filter/advanced/MagicAmaroFilter.h"
+#include "filter/advanced/MagicAntiqueFilter.h"
+#include "filter/advanced/MagicBlackCatFilter.h"
+#include "filter/advanced/MagicBrannanFilter.h"
+#include "filter/advanced/MagicBrooklynFilter.h"
+#include "filter/advanced/MagicCalmFilter.h"
+#include "filter/advanced/MagicCoolFilter.h"
+#include "filter/advanced/MagicCrayonFilter.h"
+#include "filter/advanced/MagicEarlyBirdFilter.h"
+#include "filter/advanced/MagicEmeraldFilter.h"
+#include "filter/advanced/MagicEvergreenFilter.h"
+#include "filter/advanced/MagicFreudFilter.h"
+#include "filter/advanced/MagicFairytableFilter.h"
+#include "filter/advanced/MagicHealthyFilter.h"
+#include "filter/advanced/MagicHefeFilter.h"
+#include "filter/advanced/MagicHudsonFilter.h"
+#include "filter/advanced/MagicInkwellFilter.h"
+#include "filter/advanced/MagicKevinFilter.h"
+#include "filter/advanced/MagicLatteFilter.h"
+#include "filter/advanced/MagicLomoFilter.h"
+#include "filter/advanced/MagicN1977Filter.h"
+#include "filter/advanced/MagicNashvilleFilter.h"
+#include "filter/advanced/MagicNostalgiaFilter.h"
+#include
+#include "filter/advanced/MagicPixarFilter.h"
+#include "filter/advanced/MagicRiseFilter.h"
+#include "filter/advanced/MagicRomanceFilter.h"
+#include "filter/advanced/MagicSakuraFilter.h"
+#include "filter/advanced/MagicSierraFilter.h"
+#include "filter/advanced/MagicSketchFilter.h"
+#include "filter/advanced/MagicSkinWhiteFilter.h"
+#include "filter/advanced/MagicSunriseFilter.h"
+#include "filter/advanced/MagicSunsetFilter.h"
+#include "filter/advanced/MagicSutroFilter.h"
+#include "filter/advanced/MagicSweetsFilter.h"
+#include "filter/advanced/MagicTenderFilter.h"
+#include "filter/advanced/MagicToasterFilter.h"
+#include "filter/advanced/MagicValenciaFilter.h"
+#include "filter/advanced/MagicWaldenFilter.h"
+#include "filter/advanced/MagicWarmFilter.h"
+#include "filter/advanced/MagicWhiteCatFilter.h"
+#include "filter/advanced/MagicXproIIFilter.h"
+#include "filter/douyin/MagicSoulOutFilter.h"
+#include "filter/douyin/MagicGlitchFilter.h"
+#include "filter/douyin/MagicScaleFilter.h"
+#include "filter/douyin/MagicShineWhiteFilter.h"
+#include "filter/douyin/MagicShakeEffectFilter.h"
+#include "filter/douyin/MagicVerigoFilter.h"
+#include "filter/douyin/MagicThreeWinFilter.h"
+#include "utils/OpenglUtils.h"
#define LOG_TAG "MagicFilterFactory"
#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
@@ -145,6 +146,8 @@ GPUImageFilter* initFilters(int type,AAssetManager* assetManager){
return new MagicSweetsFilter(assetManager);
case TENDER:
return new MagicTenderFilter(assetManager);
+ case THREEWIN:
+ return new MagicThreeWinFilter(assetManager);
case TOASTER2:
return new MagicToasterFilter(assetManager);
case VALENCIA:
@@ -173,6 +176,7 @@ int* getFilterTypes(int &len){
SCALE,
SHINEWHITE,
VERIGO,
+ THREEWIN,
FAIRYTALE,
SUNRISE,
SUNSET,
diff --git a/app/src/main/cpp/filter/MagicFilterFactory.h b/filter/src/main/cpp/filter/MagicFilterFactory.h
similarity index 94%
rename from app/src/main/cpp/filter/MagicFilterFactory.h
rename to filter/src/main/cpp/filter/MagicFilterFactory.h
index 176c52f..036b5be 100644
--- a/app/src/main/cpp/filter/MagicFilterFactory.h
+++ b/filter/src/main/cpp/filter/MagicFilterFactory.h
@@ -4,7 +4,7 @@
#include
#include
#include
-#include "src/main/cpp/filter/gpuimage/GpuImageFilter.h"
+#include "filter/gpuimage/GpuImageFilter.h"
/**
* cangwang 2018.12.1
@@ -17,6 +17,7 @@ enum MagicFilterType{
SCALE,
SHINEWHITE,
VERIGO,
+ THREEWIN,
FAIRYTALE,
SUNRISE,
SUNSET,
diff --git a/filter/src/main/cpp/filter/advanced/MagicAmaroFilter.cpp b/filter/src/main/cpp/filter/advanced/MagicAmaroFilter.cpp
new file mode 100644
index 0000000..60c3afa
--- /dev/null
+++ b/filter/src/main/cpp/filter/advanced/MagicAmaroFilter.cpp
@@ -0,0 +1,74 @@
+#include
+#include "MagicAmaroFilter.h"
+#include "utils/OpenglUtils.h"
+#define LOG_TAG "MagicAmaroFilter"
+#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
+#if DEBUG
+#define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
+#else
+#define ALOGV(...)
+#endif
+
+#define GET_ARRAY_LEN(array,len){len = (sizeof(array) / sizeof(array[0]));}
+
+/**
+ * cangwang 2018.12.1
+ */
+MagicAmaroFilter::MagicAmaroFilter(){
+
+}
+
+MagicAmaroFilter::MagicAmaroFilter(AAssetManager *assetManager)
+ : GPUImageFilter(assetManager,readShaderFromAsset(assetManager,"nofilter_v.glsl"), readShaderFromAsset(assetManager,"amaro.glsl")){
+ GET_ARRAY_LEN(inputTextureHandles,len);
+}
+
+MagicAmaroFilter::~MagicAmaroFilter() {
+
+}
+
+void MagicAmaroFilter::onDestroy() {
+ glDeleteTextures(len,inputTextureHandles);
+ *inputTextureHandles={0};
+}
+
+void MagicAmaroFilter::onDrawArraysPre() {
+ glUniform1f(mGLStrengthLocation, 1.0f);
+ for (int i = 0; i < len; ++i) {
+ if (inputTextureHandles[i] != 0) {
+ glActiveTexture(static_cast(GL_TEXTURE3 + i));
+ glBindTexture(GL_TEXTURE_2D, inputTextureHandles[i]);
+ glUniform1i(inputTextureUniformLocations[i], i+3);
+ }
+ }
+}
+
+void MagicAmaroFilter::onDrawArraysAfter() {
+ for (int i = 0; i < len; ++i) {
+ if (inputTextureHandles[i] != 0) {
+ glActiveTexture(static_cast(GL_TEXTURE3 + i));
+ glBindTexture(GL_TEXTURE_2D, inputTextureHandles[i]);
+ glActiveTexture(GL_TEXTURE0);
+ }
+ }
+}
+
+
+void MagicAmaroFilter::onInit() {
+ GPUImageFilter::onInit();
+ ALOGE("onInit");
+ for (int i = 0; i < len; ++i) {
+ std::ostringstream ss;
+ ss << "inputImageTexture" << 2+i;
+ inputTextureUniformLocations[i] = glGetUniformLocation(mGLProgId,
+ ss.str().c_str());
+ }
+ mGLStrengthLocation = glGetUniformLocation(mGLProgId,"strength");
+}
+
+void MagicAmaroFilter::onInitialized() {
+ GPUImageFilter::onInitialized();
+ inputTextureHandles[0] = loadTextureFromAssets(mAssetManager,"brannan_blowout.png");
+ inputTextureHandles[1] = loadTextureFromAssets(mAssetManager,"overlaymap.png");
+ inputTextureHandles[2] = loadTextureFromAssets(mAssetManager,"amaromap.png");
+}
\ No newline at end of file
diff --git a/app/src/main/cpp/filter/advanced/MagicAmaroFilter.h b/filter/src/main/cpp/filter/advanced/MagicAmaroFilter.h
similarity index 82%
rename from app/src/main/cpp/filter/advanced/MagicAmaroFilter.h
rename to filter/src/main/cpp/filter/advanced/MagicAmaroFilter.h
index c31c465..1766307 100644
--- a/app/src/main/cpp/filter/advanced/MagicAmaroFilter.h
+++ b/filter/src/main/cpp/filter/advanced/MagicAmaroFilter.h
@@ -1,10 +1,7 @@
-#include
-#include
#include
#include
#include
-#include
-#include "src/main/cpp/filter/gpuimage/GpuImageFilter.h"
+#include "filter/gpuimage/GpuImageFilter.h"
/**
* cangwang 2018.12.1
diff --git a/app/src/main/cpp/filter/advanced/MagicAntiqueFilter.cpp b/filter/src/main/cpp/filter/advanced/MagicAntiqueFilter.cpp
similarity index 99%
rename from app/src/main/cpp/filter/advanced/MagicAntiqueFilter.cpp
rename to filter/src/main/cpp/filter/advanced/MagicAntiqueFilter.cpp
index 75f1609..3a0b2bf 100644
--- a/app/src/main/cpp/filter/advanced/MagicAntiqueFilter.cpp
+++ b/filter/src/main/cpp/filter/advanced/MagicAntiqueFilter.cpp
@@ -1,5 +1,5 @@
#include "MagicAntiqueFilter.h"
-#include "src/main/cpp/utils/OpenglUtils.h"
+#include "utils/OpenglUtils.h"
#define LOG_TAG "MagicAntiqueFilter"
#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
diff --git a/app/src/main/cpp/filter/advanced/MagicAntiqueFilter.h b/filter/src/main/cpp/filter/advanced/MagicAntiqueFilter.h
similarity index 81%
rename from app/src/main/cpp/filter/advanced/MagicAntiqueFilter.h
rename to filter/src/main/cpp/filter/advanced/MagicAntiqueFilter.h
index c8431a1..3532c2a 100644
--- a/app/src/main/cpp/filter/advanced/MagicAntiqueFilter.h
+++ b/filter/src/main/cpp/filter/advanced/MagicAntiqueFilter.h
@@ -1,10 +1,7 @@
-#include
-#include
#include
#include
#include
-#include
-#include "src/main/cpp/filter/gpuimage/GpuImageFilter.h"
+#include "filter/gpuimage/GpuImageFilter.h"
/**
* cangwang 2018.12.1
diff --git a/app/src/main/cpp/filter/advanced/MagicBeautyFilter.cpp b/filter/src/main/cpp/filter/advanced/MagicBeautyFilter.cpp
similarity index 97%
rename from app/src/main/cpp/filter/advanced/MagicBeautyFilter.cpp
rename to filter/src/main/cpp/filter/advanced/MagicBeautyFilter.cpp
index e2d90c9..b54bfa6 100644
--- a/app/src/main/cpp/filter/advanced/MagicBeautyFilter.cpp
+++ b/filter/src/main/cpp/filter/advanced/MagicBeautyFilter.cpp
@@ -1,5 +1,5 @@
#include "MagicBeautyFilter.h"
-#include "src/main/cpp/utils/OpenglUtils.h"
+#include "utils/OpenglUtils.h"
#define LOG_TAG "MagicBeautyFilter"
#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
diff --git a/app/src/main/cpp/filter/advanced/MagicBeautyFilter.h b/filter/src/main/cpp/filter/advanced/MagicBeautyFilter.h
similarity index 93%
rename from app/src/main/cpp/filter/advanced/MagicBeautyFilter.h
rename to filter/src/main/cpp/filter/advanced/MagicBeautyFilter.h
index 3398ecc..f15914c 100644
--- a/app/src/main/cpp/filter/advanced/MagicBeautyFilter.h
+++ b/filter/src/main/cpp/filter/advanced/MagicBeautyFilter.h
@@ -4,7 +4,7 @@
#include
#include
#include
-#include "src/main/cpp/filter/gpuimage/GpuImageFilter.h"
+#include "filter/gpuimage/GpuImageFilter.h"
/**
* cangwang 2018.12.1
diff --git a/app/src/main/cpp/filter/advanced/MagicBlackCatFilter.cpp b/filter/src/main/cpp/filter/advanced/MagicBlackCatFilter.cpp
similarity index 99%
rename from app/src/main/cpp/filter/advanced/MagicBlackCatFilter.cpp
rename to filter/src/main/cpp/filter/advanced/MagicBlackCatFilter.cpp
index 7b793ac..a623704 100644
--- a/app/src/main/cpp/filter/advanced/MagicBlackCatFilter.cpp
+++ b/filter/src/main/cpp/filter/advanced/MagicBlackCatFilter.cpp
@@ -1,5 +1,5 @@
#include "MagicBlackCatFilter.h"
-#include "src/main/cpp/utils/OpenglUtils.h"
+#include "utils/OpenglUtils.h"
#define LOG_TAG "MagicBlackCatFilter"
#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
diff --git a/app/src/main/cpp/filter/advanced/MagicBlackCatFilter.h b/filter/src/main/cpp/filter/advanced/MagicBlackCatFilter.h
similarity index 91%
rename from app/src/main/cpp/filter/advanced/MagicBlackCatFilter.h
rename to filter/src/main/cpp/filter/advanced/MagicBlackCatFilter.h
index 053c410..5902ef2 100644
--- a/app/src/main/cpp/filter/advanced/MagicBlackCatFilter.h
+++ b/filter/src/main/cpp/filter/advanced/MagicBlackCatFilter.h
@@ -4,7 +4,7 @@
#include
#include
#include
-#include "src/main/cpp/filter/gpuimage/GpuImageFilter.h"
+#include "filter/gpuimage/GpuImageFilter.h"
/**
* cangwang 2018.12.1
diff --git a/filter/src/main/cpp/filter/advanced/MagicBrannanFilter.cpp b/filter/src/main/cpp/filter/advanced/MagicBrannanFilter.cpp
new file mode 100644
index 0000000..930c08d
--- /dev/null
+++ b/filter/src/main/cpp/filter/advanced/MagicBrannanFilter.cpp
@@ -0,0 +1,77 @@
+#include
+#include "MagicBrannanFilter.h"
+#include "utils/OpenglUtils.h"
+
+#define LOG_TAG "MagicBrannanFilter"
+#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
+#if DEBUG
+#define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
+#else
+#define ALOGV(...)
+#endif
+
+#define GET_ARRAY_LEN(array,len){len = (sizeof(array) / sizeof(array[0]));}
+
+/**
+ * cangwang 2018.12.1
+ */
+MagicBrannanFilter::MagicBrannanFilter(){
+
+}
+
+MagicBrannanFilter::MagicBrannanFilter(AAssetManager *assetManager)
+ : GPUImageFilter(assetManager,readShaderFromAsset(assetManager,"nofilter_v.glsl"), readShaderFromAsset(assetManager,"brannan.glsl")){
+ GET_ARRAY_LEN(inputTextureHandles,len);
+}
+
+MagicBrannanFilter::~MagicBrannanFilter() {
+
+}
+
+void MagicBrannanFilter::onDestroy() {
+ glDeleteTextures(len,inputTextureHandles);
+ *inputTextureHandles= {0};
+}
+
+void MagicBrannanFilter::onDrawArraysPre() {
+ glUniform1f(mGLStrengthLocation, 1.0f);
+ for (int i = 0; i < len; ++i) {
+ if (inputTextureHandles[i] != 0) {
+ glActiveTexture(GL_TEXTURE3 + i);
+ glBindTexture(GL_TEXTURE_2D, inputTextureHandles[i]);
+ glUniform1i(inputTextureUniformLocations[i], i+3);
+ }
+ }
+}
+
+void MagicBrannanFilter::onDrawArraysAfter() {
+ for (int i = 0; i < len; ++i) {
+ if (inputTextureHandles[i] != 0) {
+ glActiveTexture(GL_TEXTURE3 + i);
+ glBindTexture(GL_TEXTURE_2D, inputTextureHandles[i]);
+ glActiveTexture(GL_TEXTURE0);
+ }
+ }
+}
+
+
+void MagicBrannanFilter::onInit() {
+ GPUImageFilter::onInit();
+ for (int i = 0; i < len; ++i) {
+ std::ostringstream ss;
+ ss << "inputImageTexture" << 2+i;
+ inputTextureUniformLocations[i] = glGetUniformLocation(mGLProgId,
+ ss.str().c_str());
+ }
+ mGLStrengthLocation = glGetUniformLocation(mGLProgId,"strength");
+}
+
+void MagicBrannanFilter::onInitialized() {
+ GPUImageFilter::onInitialized();
+ inputTextureHandles[0] = loadTextureFromAssets(mAssetManager,"brannan_process.png");
+ inputTextureHandles[1] = loadTextureFromAssets(mAssetManager,"brannan_blowout.png");
+ inputTextureHandles[2] = loadTextureFromAssets(mAssetManager,"brannan_contrast.png");
+ inputTextureHandles[3] = loadTextureFromAssets(mAssetManager,"brannan_luma.png");
+ inputTextureHandles[4] = loadTextureFromAssets(mAssetManager,"brannan_screen.png");
+
+}
\ No newline at end of file
diff --git a/app/src/main/cpp/filter/advanced/MagicBrannanFilter.h b/filter/src/main/cpp/filter/advanced/MagicBrannanFilter.h
similarity index 91%
rename from app/src/main/cpp/filter/advanced/MagicBrannanFilter.h
rename to filter/src/main/cpp/filter/advanced/MagicBrannanFilter.h
index 2da6e7b..9fbbdb1 100644
--- a/app/src/main/cpp/filter/advanced/MagicBrannanFilter.h
+++ b/filter/src/main/cpp/filter/advanced/MagicBrannanFilter.h
@@ -4,7 +4,7 @@
#include
#include
#include
-#include "src/main/cpp/filter/gpuimage/GpuImageFilter.h"
+#include "filter/gpuimage/GpuImageFilter.h"
/**
* cangwang 2018.12.1
diff --git a/filter/src/main/cpp/filter/advanced/MagicBrooklynFilter.cpp b/filter/src/main/cpp/filter/advanced/MagicBrooklynFilter.cpp
new file mode 100644
index 0000000..fd2f028
--- /dev/null
+++ b/filter/src/main/cpp/filter/advanced/MagicBrooklynFilter.cpp
@@ -0,0 +1,75 @@
+#include
+#include "MagicBrooklynFilter.h"
+#include "utils/OpenglUtils.h"
+
+#define LOG_TAG "MagicBrooklynFilter"
+#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
+#if DEBUG
+#define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
+#else
+#define ALOGV(...)
+#endif
+
+#define GET_ARRAY_LEN(array,len){len = (sizeof(array) / sizeof(array[0]));}
+
+/**
+ * cangwang 2018.12.1
+ */
+MagicBrooklynFilter::MagicBrooklynFilter(){
+
+}
+
+MagicBrooklynFilter::MagicBrooklynFilter(AAssetManager *assetManager)
+ : GPUImageFilter(assetManager,readShaderFromAsset(assetManager,"nofilter_v.glsl"), readShaderFromAsset(assetManager,"brooklyn.glsl")){
+ GET_ARRAY_LEN(inputTextureHandles,len);
+}
+
+MagicBrooklynFilter::~MagicBrooklynFilter() {
+
+}
+
+void MagicBrooklynFilter::onDestroy() {
+ glDeleteTextures(len,inputTextureHandles);
+ *inputTextureHandles={0};
+}
+
+void MagicBrooklynFilter::onDrawArraysPre() {
+ glUniform1f(mGLStrengthLocation, 1.0f);
+ for (int i = 0; i < len; ++i) {
+ if (inputTextureHandles[i] != 0) {
+ glActiveTexture(static_cast(GL_TEXTURE3 + i));
+ glBindTexture(GL_TEXTURE_2D, inputTextureHandles[i]);
+ glUniform1i(inputTextureUniformLocations[i], 3);
+ }
+ }
+}
+
+void MagicBrooklynFilter::onDrawArraysAfter() {
+ for (int i = 0; i < len; ++i) {
+ if (inputTextureHandles[i] != 0) {
+ glActiveTexture(static_cast(GL_TEXTURE3 + i));
+ glBindTexture(GL_TEXTURE_2D, inputTextureHandles[i]);
+ glActiveTexture(GL_TEXTURE0);
+ }
+ }
+
+}
+
+
+void MagicBrooklynFilter::onInit() {
+ GPUImageFilter::onInit();
+ for (int i = 0; i < len; ++i) {
+ std::ostringstream ss;
+ ss << "inputImageTexture" << 2+i;
+ inputTextureUniformLocations[i] = glGetUniformLocation(mGLProgId,
+ ss.str().c_str());
+ }
+ mGLStrengthLocation = glGetUniformLocation(mGLProgId,"strength");
+}
+
+void MagicBrooklynFilter::onInitialized() {
+ GPUImageFilter::onInitialized();
+ inputTextureHandles[0] = loadTextureFromAssets(mAssetManager,"brooklynCurves1.png");
+ inputTextureHandles[1] = loadTextureFromAssets(mAssetManager,"filter_map_first.png");
+ inputTextureHandles[2] = loadTextureFromAssets(mAssetManager,"brooklynCurves2.png");
+}
\ No newline at end of file
diff --git a/app/src/main/cpp/filter/advanced/MagicBrooklynFilter.h b/filter/src/main/cpp/filter/advanced/MagicBrooklynFilter.h
similarity index 91%
rename from app/src/main/cpp/filter/advanced/MagicBrooklynFilter.h
rename to filter/src/main/cpp/filter/advanced/MagicBrooklynFilter.h
index 358c4ce..e138c7d 100644
--- a/app/src/main/cpp/filter/advanced/MagicBrooklynFilter.h
+++ b/filter/src/main/cpp/filter/advanced/MagicBrooklynFilter.h
@@ -4,7 +4,7 @@
#include
#include
#include
-#include "src/main/cpp/filter/gpuimage/GpuImageFilter.h"
+#include "filter/gpuimage/GpuImageFilter.h"
/**
* cangwang 2018.12.1
diff --git a/app/src/main/cpp/filter/advanced/MagicCalmFilter.cpp b/filter/src/main/cpp/filter/advanced/MagicCalmFilter.cpp
similarity index 99%
rename from app/src/main/cpp/filter/advanced/MagicCalmFilter.cpp
rename to filter/src/main/cpp/filter/advanced/MagicCalmFilter.cpp
index 100b1ee..c6e211a 100644
--- a/app/src/main/cpp/filter/advanced/MagicCalmFilter.cpp
+++ b/filter/src/main/cpp/filter/advanced/MagicCalmFilter.cpp
@@ -1,5 +1,5 @@
#include "MagicCalmFilter.h"
-#include "src/main/cpp/utils/OpenglUtils.h"
+#include "utils/OpenglUtils.h"
#define LOG_TAG "MagicCalmFilter"
#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
diff --git a/app/src/main/cpp/filter/advanced/MagicCalmFilter.h b/filter/src/main/cpp/filter/advanced/MagicCalmFilter.h
similarity index 92%
rename from app/src/main/cpp/filter/advanced/MagicCalmFilter.h
rename to filter/src/main/cpp/filter/advanced/MagicCalmFilter.h
index 6a3c24a..959d306 100644
--- a/app/src/main/cpp/filter/advanced/MagicCalmFilter.h
+++ b/filter/src/main/cpp/filter/advanced/MagicCalmFilter.h
@@ -4,7 +4,7 @@
#include
#include
#include
-#include "src/main/cpp/filter/gpuimage/GpuImageFilter.h"
+#include "filter/gpuimage/GpuImageFilter.h"
/**
* cangwang 2018.12.1
diff --git a/app/src/main/cpp/filter/advanced/MagicCoolFilter.cpp b/filter/src/main/cpp/filter/advanced/MagicCoolFilter.cpp
similarity index 99%
rename from app/src/main/cpp/filter/advanced/MagicCoolFilter.cpp
rename to filter/src/main/cpp/filter/advanced/MagicCoolFilter.cpp
index 69bc08c..02e447b 100644
--- a/app/src/main/cpp/filter/advanced/MagicCoolFilter.cpp
+++ b/filter/src/main/cpp/filter/advanced/MagicCoolFilter.cpp
@@ -1,5 +1,5 @@
#include "MagicCoolFilter.h"
-#include "src/main/cpp/utils/OpenglUtils.h"
+#include "utils/OpenglUtils.h"
#define LOG_TAG "MagicCoolFilter"
#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
diff --git a/app/src/main/cpp/filter/advanced/MagicCoolFilter.h b/filter/src/main/cpp/filter/advanced/MagicCoolFilter.h
similarity index 91%
rename from app/src/main/cpp/filter/advanced/MagicCoolFilter.h
rename to filter/src/main/cpp/filter/advanced/MagicCoolFilter.h
index ffc6031..7964137 100644
--- a/app/src/main/cpp/filter/advanced/MagicCoolFilter.h
+++ b/filter/src/main/cpp/filter/advanced/MagicCoolFilter.h
@@ -4,7 +4,7 @@
#include
#include
#include
-#include "src/main/cpp/filter/gpuimage/GpuImageFilter.h"
+#include "filter/gpuimage/GpuImageFilter.h"
/**
* cangwang 2018.12.1
diff --git a/app/src/main/cpp/filter/advanced/MagicCrayonFilter.cpp b/filter/src/main/cpp/filter/advanced/MagicCrayonFilter.cpp
similarity index 97%
rename from app/src/main/cpp/filter/advanced/MagicCrayonFilter.cpp
rename to filter/src/main/cpp/filter/advanced/MagicCrayonFilter.cpp
index 2548d06..8fbf886 100644
--- a/app/src/main/cpp/filter/advanced/MagicCrayonFilter.cpp
+++ b/filter/src/main/cpp/filter/advanced/MagicCrayonFilter.cpp
@@ -1,5 +1,5 @@
#include "MagicCrayonFilter.h"
-#include "src/main/cpp/utils/OpenglUtils.h"
+#include "utils/OpenglUtils.h"
#define LOG_TAG "MagicCrayonFilter"
#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
diff --git a/app/src/main/cpp/filter/advanced/MagicCrayonFilter.h b/filter/src/main/cpp/filter/advanced/MagicCrayonFilter.h
similarity index 92%
rename from app/src/main/cpp/filter/advanced/MagicCrayonFilter.h
rename to filter/src/main/cpp/filter/advanced/MagicCrayonFilter.h
index d89a8b9..8142ba1 100644
--- a/app/src/main/cpp/filter/advanced/MagicCrayonFilter.h
+++ b/filter/src/main/cpp/filter/advanced/MagicCrayonFilter.h
@@ -4,7 +4,7 @@
#include
#include
#include
-#include "src/main/cpp/filter/gpuimage/GpuImageFilter.h"
+#include "filter/gpuimage/GpuImageFilter.h"
/**
* cangwang 2018.12.1
diff --git a/filter/src/main/cpp/filter/advanced/MagicEarlyBirdFilter.cpp b/filter/src/main/cpp/filter/advanced/MagicEarlyBirdFilter.cpp
new file mode 100644
index 0000000..f354ff6
--- /dev/null
+++ b/filter/src/main/cpp/filter/advanced/MagicEarlyBirdFilter.cpp
@@ -0,0 +1,78 @@
+#include
+#include "MagicEarlyBirdFilter.h"
+#include "utils/OpenglUtils.h"
+
+#define LOG_TAG "MagicEarlyBirdFilter"
+#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
+#if DEBUG
+#define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
+#else
+#define ALOGV(...)
+#endif
+
+#define GET_ARRAY_LEN(array,len){len = (sizeof(array) / sizeof(array[0]));}
+
+/**
+ * cangwang 2018.12.1
+ */
+MagicEarlyBirdFilter::MagicEarlyBirdFilter(){
+
+}
+
+MagicEarlyBirdFilter::MagicEarlyBirdFilter(AAssetManager *assetManager)
+ : GPUImageFilter(assetManager,readShaderFromAsset(assetManager,"nofilter_v.glsl"), readShaderFromAsset(assetManager,"brannan.glsl")){
+ GET_ARRAY_LEN(inputTextureHandles,len);
+}
+
+MagicEarlyBirdFilter::~MagicEarlyBirdFilter() {
+
+}
+
+void MagicEarlyBirdFilter::onDestroy() {
+ glDeleteTextures(len,inputTextureHandles);
+ *inputTextureHandles={0};
+}
+
+void MagicEarlyBirdFilter::onDrawArraysPre() {
+ glUniform1f(mGLStrengthLocation, 1.0f);
+ for (int i = 0; i < len; ++i) {
+ if (inputTextureHandles[i] != 0) {
+ glActiveTexture(static_cast(GL_TEXTURE3 + i));
+ glBindTexture(GL_TEXTURE_2D, inputTextureHandles[i]);
+ glUniform1i(inputTextureUniformLocations[i], (i+3));
+ }
+ }
+}
+
+void MagicEarlyBirdFilter::onDrawArraysAfter() {
+ for (int i = 0; i < len; ++i) {
+ if (inputTextureHandles[i] != 0) {
+ glActiveTexture(static_cast(GL_TEXTURE3 + i));
+ glBindTexture(GL_TEXTURE_2D, inputTextureHandles[i]);
+ glActiveTexture(GL_TEXTURE0);
+ }
+ }
+}
+
+
+void MagicEarlyBirdFilter::onInit() {
+ GPUImageFilter::onInit();
+ for (int i = 0; i < len; ++i) {
+ std::ostringstream ss;
+ ss << "inputImageTexture" << 2+i;
+ inputTextureUniformLocations[i] = glGetUniformLocation(mGLProgId,
+ ss.str().c_str());
+ }
+ mGLStrengthLocation = glGetUniformLocation(mGLProgId,"strength");
+}
+
+void MagicEarlyBirdFilter::onInitialized() {
+ GPUImageFilter::onInitialized();
+
+ inputTextureHandles[0] = loadTextureFromAssets(mAssetManager,"earlybirdcurves.png");
+ inputTextureHandles[1] = loadTextureFromAssets(mAssetManager,"earlybirdoverlaymap_new.png");
+ inputTextureHandles[2] = loadTextureFromAssets(mAssetManager,"vignettemap_new.png");
+ inputTextureHandles[3] = loadTextureFromAssets(mAssetManager,"earlybirdblowout.png");
+ inputTextureHandles[4] = loadTextureFromAssets(mAssetManager,"earlybirdmap.png");
+
+}
\ No newline at end of file
diff --git a/app/src/main/cpp/filter/advanced/MagicEarlyBirdFilter.h b/filter/src/main/cpp/filter/advanced/MagicEarlyBirdFilter.h
similarity index 91%
rename from app/src/main/cpp/filter/advanced/MagicEarlyBirdFilter.h
rename to filter/src/main/cpp/filter/advanced/MagicEarlyBirdFilter.h
index d1cc5fb..cd544a8 100644
--- a/app/src/main/cpp/filter/advanced/MagicEarlyBirdFilter.h
+++ b/filter/src/main/cpp/filter/advanced/MagicEarlyBirdFilter.h
@@ -4,7 +4,7 @@
#include
#include
#include
-#include "src/main/cpp/filter/gpuimage/GpuImageFilter.h"
+#include "filter/gpuimage/GpuImageFilter.h"
/**
* cangwang 2018.12.1
diff --git a/app/src/main/cpp/filter/advanced/MagicEmeraldFilter.cpp b/filter/src/main/cpp/filter/advanced/MagicEmeraldFilter.cpp
similarity index 99%
rename from app/src/main/cpp/filter/advanced/MagicEmeraldFilter.cpp
rename to filter/src/main/cpp/filter/advanced/MagicEmeraldFilter.cpp
index c37d1c5..49097b9 100644
--- a/app/src/main/cpp/filter/advanced/MagicEmeraldFilter.cpp
+++ b/filter/src/main/cpp/filter/advanced/MagicEmeraldFilter.cpp
@@ -1,5 +1,5 @@
#include "MagicEmeraldFilter.h"
-#include "src/main/cpp/utils/OpenglUtils.h"
+#include "utils/OpenglUtils.h"
#define LOG_TAG "MagicEmeraldFilter"
#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
diff --git a/app/src/main/cpp/filter/advanced/MagicEmeraldFilter.h b/filter/src/main/cpp/filter/advanced/MagicEmeraldFilter.h
similarity index 91%
rename from app/src/main/cpp/filter/advanced/MagicEmeraldFilter.h
rename to filter/src/main/cpp/filter/advanced/MagicEmeraldFilter.h
index 02b30f6..27c88e7 100644
--- a/app/src/main/cpp/filter/advanced/MagicEmeraldFilter.h
+++ b/filter/src/main/cpp/filter/advanced/MagicEmeraldFilter.h
@@ -4,7 +4,7 @@
#include
#include
#include
-#include "src/main/cpp/filter/gpuimage/GpuImageFilter.h"
+#include "filter/gpuimage/GpuImageFilter.h"
/**
* cangwang 2018.12.1
diff --git a/app/src/main/cpp/filter/advanced/MagicEvergreenFilter.cpp b/filter/src/main/cpp/filter/advanced/MagicEvergreenFilter.cpp
similarity index 99%
rename from app/src/main/cpp/filter/advanced/MagicEvergreenFilter.cpp
rename to filter/src/main/cpp/filter/advanced/MagicEvergreenFilter.cpp
index 7190d63..5b206d9 100644
--- a/app/src/main/cpp/filter/advanced/MagicEvergreenFilter.cpp
+++ b/filter/src/main/cpp/filter/advanced/MagicEvergreenFilter.cpp
@@ -1,5 +1,5 @@
#include "MagicEvergreenFilter.h"
-#include "src/main/cpp/utils/OpenglUtils.h"
+#include "utils/OpenglUtils.h"
#define LOG_TAG "MagicEvergreenFilter"
#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
diff --git a/app/src/main/cpp/filter/advanced/MagicEvergreenFilter.h b/filter/src/main/cpp/filter/advanced/MagicEvergreenFilter.h
similarity index 91%
rename from app/src/main/cpp/filter/advanced/MagicEvergreenFilter.h
rename to filter/src/main/cpp/filter/advanced/MagicEvergreenFilter.h
index d30b1eb..a3b498f 100644
--- a/app/src/main/cpp/filter/advanced/MagicEvergreenFilter.h
+++ b/filter/src/main/cpp/filter/advanced/MagicEvergreenFilter.h
@@ -4,7 +4,7 @@
#include
#include
#include
-#include "src/main/cpp/filter/gpuimage/GpuImageFilter.h"
+#include "filter/gpuimage/GpuImageFilter.h"
/**
* cangwang 2018.12.1
diff --git a/app/src/main/cpp/filter/advanced/MagicFairytableFilter.cpp b/filter/src/main/cpp/filter/advanced/MagicFairytableFilter.cpp
similarity index 93%
rename from app/src/main/cpp/filter/advanced/MagicFairytableFilter.cpp
rename to filter/src/main/cpp/filter/advanced/MagicFairytableFilter.cpp
index b1d5eb3..6ed66ce 100644
--- a/app/src/main/cpp/filter/advanced/MagicFairytableFilter.cpp
+++ b/filter/src/main/cpp/filter/advanced/MagicFairytableFilter.cpp
@@ -1,5 +1,5 @@
#include "MagicFairytableFilter.h"
-#include "src/main/cpp/utils/OpenglUtils.h"
+#include "utils/OpenglUtils.h"
#define LOG_TAG "MagicFairytableFilter"
#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
diff --git a/app/src/main/cpp/filter/advanced/MagicFairytableFilter.h b/filter/src/main/cpp/filter/advanced/MagicFairytableFilter.h
similarity index 84%
rename from app/src/main/cpp/filter/advanced/MagicFairytableFilter.h
rename to filter/src/main/cpp/filter/advanced/MagicFairytableFilter.h
index d22a8cb..fecd535 100644
--- a/app/src/main/cpp/filter/advanced/MagicFairytableFilter.h
+++ b/filter/src/main/cpp/filter/advanced/MagicFairytableFilter.h
@@ -4,7 +4,7 @@
#include
#include
#include
-#include "src/main/cpp/filter/advanced/MagicLookupFilter.h"
+#include "MagicLookupFilter.h"
/**
* cangwang 2018.12.17
diff --git a/app/src/main/cpp/filter/advanced/MagicFreudFilter.cpp b/filter/src/main/cpp/filter/advanced/MagicFreudFilter.cpp
similarity index 99%
rename from app/src/main/cpp/filter/advanced/MagicFreudFilter.cpp
rename to filter/src/main/cpp/filter/advanced/MagicFreudFilter.cpp
index bf87c8f..d2b28b6 100644
--- a/app/src/main/cpp/filter/advanced/MagicFreudFilter.cpp
+++ b/filter/src/main/cpp/filter/advanced/MagicFreudFilter.cpp
@@ -1,5 +1,5 @@
#include "MagicFreudFilter.h"
-#include "src/main/cpp/utils/OpenglUtils.h"
+#include "utils/OpenglUtils.h"
#define LOG_TAG "MagicFreudFilter"
#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
diff --git a/app/src/main/cpp/filter/advanced/MagicFreudFilter.h b/filter/src/main/cpp/filter/advanced/MagicFreudFilter.h
similarity index 91%
rename from app/src/main/cpp/filter/advanced/MagicFreudFilter.h
rename to filter/src/main/cpp/filter/advanced/MagicFreudFilter.h
index 8994431..7482712 100644
--- a/app/src/main/cpp/filter/advanced/MagicFreudFilter.h
+++ b/filter/src/main/cpp/filter/advanced/MagicFreudFilter.h
@@ -4,7 +4,7 @@
#include
#include
#include
-#include "src/main/cpp/filter/gpuimage/GpuImageFilter.h"
+#include "filter/gpuimage/GpuImageFilter.h"
/**
* cangwang 2018.12.1
diff --git a/app/src/main/cpp/filter/advanced/MagicHealthyFilter.cpp b/filter/src/main/cpp/filter/advanced/MagicHealthyFilter.cpp
similarity index 99%
rename from app/src/main/cpp/filter/advanced/MagicHealthyFilter.cpp
rename to filter/src/main/cpp/filter/advanced/MagicHealthyFilter.cpp
index c0fa342..43030be 100644
--- a/app/src/main/cpp/filter/advanced/MagicHealthyFilter.cpp
+++ b/filter/src/main/cpp/filter/advanced/MagicHealthyFilter.cpp
@@ -1,5 +1,5 @@
#include "MagicHealthyFilter.h"
-#include "src/main/cpp/utils/OpenglUtils.h"
+#include "utils/OpenglUtils.h"
#define LOG_TAG "MagicHealthyFilter"
#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
diff --git a/app/src/main/cpp/filter/advanced/MagicHealthyFilter.h b/filter/src/main/cpp/filter/advanced/MagicHealthyFilter.h
similarity index 93%
rename from app/src/main/cpp/filter/advanced/MagicHealthyFilter.h
rename to filter/src/main/cpp/filter/advanced/MagicHealthyFilter.h
index 9aac0dc..cafa009 100644
--- a/app/src/main/cpp/filter/advanced/MagicHealthyFilter.h
+++ b/filter/src/main/cpp/filter/advanced/MagicHealthyFilter.h
@@ -4,7 +4,7 @@
#include
#include
#include ]