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 @@ + + + + + + + +