├── java_demo
├── .gitignore
├── libs
│ ├── gson-2.8.5.jar
│ └── renderer-camera-release.aar
├── src
│ └── main
│ │ ├── res
│ │ ├── values
│ │ │ ├── strings.xml
│ │ │ ├── colors.xml
│ │ │ └── styles.xml
│ │ ├── mipmap-xxhdpi
│ │ │ ├── sample.png
│ │ │ └── ic_launcher.png
│ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.png
│ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher.png
│ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher.png
│ │ ├── mipmap-xxxhdpi
│ │ │ └── ic_launcher.png
│ │ └── layout
│ │ │ └── activity_main.xml
│ │ ├── ic_launcher-web.png
│ │ ├── java
│ │ └── co
│ │ │ └── polarr
│ │ │ └── polarrcamerademo
│ │ │ ├── OESTexture.java
│ │ │ ├── FaceUtil.java
│ │ │ ├── MainActivity.java
│ │ │ └── CameraRenderView.java
│ │ └── AndroidManifest.xml
├── release
│ └── Polarr_Lut_SDK_1.2.apk
├── proguard-rules.pro
├── build.gradle
├── README_zh.md
└── README.md
├── settings.gradle
├── c_demo
├── .gitignore
├── src
│ └── main
│ │ ├── assets
│ │ └── yuv.dat
│ │ ├── ic_launcher-web.png
│ │ ├── cpp
│ │ ├── jnis
│ │ │ ├── x86
│ │ │ │ └── libPolarrRender.so
│ │ │ ├── x86_64
│ │ │ │ └── libPolarrRender.so
│ │ │ ├── arm64-v8a
│ │ │ │ └── libPolarrRender.so
│ │ │ ├── armeabi
│ │ │ │ └── libPolarrRender.so
│ │ │ └── armeabi-v7a
│ │ │ │ └── libPolarrRender.so
│ │ ├── CMakeLists.txt
│ │ ├── include
│ │ │ └── polarrRender.h
│ │ └── polarrRenderJni.cpp
│ │ ├── res
│ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.png
│ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher.png
│ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher.png
│ │ ├── mipmap-xxhdpi
│ │ │ └── ic_launcher.png
│ │ ├── mipmap-xxxhdpi
│ │ │ └── ic_launcher.png
│ │ ├── values
│ │ │ └── strings.xml
│ │ └── layout
│ │ │ └── activity_fullscreen.xml
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── co
│ │ └── polarr
│ │ ├── render
│ │ └── PolarrRenderJni.java
│ │ └── renderdemoclib
│ │ └── MainActivity.java
├── proguard-rules.pro
├── build.gradle
├── README_zh.md
└── README.md
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── README_zh.md
├── README.md
├── gradle.properties
├── .gitignore
├── gradlew.bat
└── gradlew
/java_demo/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':c_demo', ':java_demo'
2 |
--------------------------------------------------------------------------------
/c_demo/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | /.externalNativeBuild
3 | /.google
4 | /.idea
5 | /.gradle
--------------------------------------------------------------------------------
/c_demo/src/main/assets/yuv.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polarrco/PolarrCameraAndroidSDK/HEAD/c_demo/src/main/assets/yuv.dat
--------------------------------------------------------------------------------
/java_demo/libs/gson-2.8.5.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polarrco/PolarrCameraAndroidSDK/HEAD/java_demo/libs/gson-2.8.5.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polarrco/PolarrCameraAndroidSDK/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/c_demo/src/main/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polarrco/PolarrCameraAndroidSDK/HEAD/c_demo/src/main/ic_launcher-web.png
--------------------------------------------------------------------------------
/java_demo/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Polarr Camera Demo
3 |
4 |
--------------------------------------------------------------------------------
/java_demo/src/main/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polarrco/PolarrCameraAndroidSDK/HEAD/java_demo/src/main/ic_launcher-web.png
--------------------------------------------------------------------------------
/java_demo/release/Polarr_Lut_SDK_1.2.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polarrco/PolarrCameraAndroidSDK/HEAD/java_demo/release/Polarr_Lut_SDK_1.2.apk
--------------------------------------------------------------------------------
/java_demo/libs/renderer-camera-release.aar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polarrco/PolarrCameraAndroidSDK/HEAD/java_demo/libs/renderer-camera-release.aar
--------------------------------------------------------------------------------
/c_demo/src/main/cpp/jnis/x86/libPolarrRender.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polarrco/PolarrCameraAndroidSDK/HEAD/c_demo/src/main/cpp/jnis/x86/libPolarrRender.so
--------------------------------------------------------------------------------
/c_demo/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polarrco/PolarrCameraAndroidSDK/HEAD/c_demo/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/c_demo/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polarrco/PolarrCameraAndroidSDK/HEAD/c_demo/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/c_demo/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polarrco/PolarrCameraAndroidSDK/HEAD/c_demo/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/java_demo/src/main/res/mipmap-xxhdpi/sample.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polarrco/PolarrCameraAndroidSDK/HEAD/java_demo/src/main/res/mipmap-xxhdpi/sample.png
--------------------------------------------------------------------------------
/c_demo/src/main/cpp/jnis/x86_64/libPolarrRender.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polarrco/PolarrCameraAndroidSDK/HEAD/c_demo/src/main/cpp/jnis/x86_64/libPolarrRender.so
--------------------------------------------------------------------------------
/c_demo/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polarrco/PolarrCameraAndroidSDK/HEAD/c_demo/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/c_demo/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polarrco/PolarrCameraAndroidSDK/HEAD/c_demo/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/java_demo/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polarrco/PolarrCameraAndroidSDK/HEAD/java_demo/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/java_demo/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polarrco/PolarrCameraAndroidSDK/HEAD/java_demo/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/c_demo/src/main/cpp/jnis/arm64-v8a/libPolarrRender.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polarrco/PolarrCameraAndroidSDK/HEAD/c_demo/src/main/cpp/jnis/arm64-v8a/libPolarrRender.so
--------------------------------------------------------------------------------
/c_demo/src/main/cpp/jnis/armeabi/libPolarrRender.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polarrco/PolarrCameraAndroidSDK/HEAD/c_demo/src/main/cpp/jnis/armeabi/libPolarrRender.so
--------------------------------------------------------------------------------
/c_demo/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | PoCam C++ Demo
4 |
5 |
--------------------------------------------------------------------------------
/java_demo/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polarrco/PolarrCameraAndroidSDK/HEAD/java_demo/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/java_demo/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polarrco/PolarrCameraAndroidSDK/HEAD/java_demo/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/java_demo/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polarrco/PolarrCameraAndroidSDK/HEAD/java_demo/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/c_demo/src/main/cpp/jnis/armeabi-v7a/libPolarrRender.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polarrco/PolarrCameraAndroidSDK/HEAD/c_demo/src/main/cpp/jnis/armeabi-v7a/libPolarrRender.so
--------------------------------------------------------------------------------
/java_demo/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #cc4285f4
4 |
5 |
--------------------------------------------------------------------------------
/README_zh.md:
--------------------------------------------------------------------------------
1 | # 泼辣滤镜Camera SDK
2 | ## 版权限制
3 | 包含本SDK在内的所有版本库中的内容,属于Polarr, Inc.版权所有。未经允许均不得用于商业目的。如需要获取完整授权等更多相关信息,请联系我们[info@polarr.co](mailto:info@polarr.co)
4 |
5 | ## Java版本
6 | [Java版本说明文档](java_demo/README_zh.md)
7 |
8 |
9 | ## C++ 版本
10 | [C++版本说明文档](c_demo/README_zh.md)
11 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sat Apr 20 13:20:50 JST 2019
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip
7 |
--------------------------------------------------------------------------------
/java_demo/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/c_demo/src/main/res/layout/activity_fullscreen.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PolarrCameraAndroidSDK
2 |
3 | *As of January 2025, the public repo of Polarr Camera Android SDK is no longer maintained. If you are interested in commercial licensing of the SDK, please reach out to [info@polarr.co](mailto:info@polarr.co)*.
4 |
5 | ## License
6 | The SDK included in this repository must not be used for any commercial purposes without the direct written consent of Polarr, Inc. The current version of the SDK expires on December 31, 2024. For pricing and more info regarding the full license SDK, please email [hello@polarr.ai](mailto:hello@polarr.ai).
7 |
8 | ## Java version
9 | [Java Version ReadMe](java_demo/README.md)
10 |
11 |
12 | ## C++ version
13 | [C++ Version ReadMe](c_demo/README.md)
14 |
--------------------------------------------------------------------------------
/c_demo/src/main/cpp/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.4.1)
2 |
3 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
4 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-rtti -fno-exceptions -Wall")
5 |
6 | add_library(PolarrRender SHARED IMPORTED)
7 |
8 | set_target_properties(PolarrRender
9 | PROPERTIES
10 | IMPORTED_LOCATION
11 | ${CMAKE_SOURCE_DIR}/jnis/${ANDROID_ABI}/libPolarrRender.so)
12 |
13 |
14 | add_library(PolarrRenderJNI SHARED
15 | polarrRenderJni.cpp)
16 |
17 | target_include_directories(PolarrRenderJNI PRIVATE
18 | ${CMAKE_SOURCE_DIR}/include)
19 |
20 | target_link_libraries(PolarrRenderJNI
21 | PolarrRender
22 | android
23 | log)
--------------------------------------------------------------------------------
/c_demo/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/java_demo/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | android.enableJetifier=true
13 | android.useAndroidX=true
14 | org.gradle.jvmargs=-Xmx1536m
15 |
16 | # When configured, Gradle will run in incubating parallel mode.
17 | # This option should only be used with decoupled projects. More details, visit
18 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
19 | # org.gradle.parallel=true
20 |
--------------------------------------------------------------------------------
/java_demo/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 30
5 | defaultConfig {
6 | applicationId "co.polarr.polarrcamerademo"
7 | minSdkVersion 19
8 | targetSdkVersion 30
9 | versionCode 8
10 | versionName "1.4"
11 | }
12 |
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | }
20 |
21 | repositories {
22 | flatDir {
23 | dirs 'libs'
24 | }
25 | google()
26 | }
27 |
28 | dependencies {
29 | implementation fileTree(dir: 'libs', include: ['*.jar'])
30 | implementation 'androidx.appcompat:appcompat:1.3.1'
31 |
32 | // render engine
33 | implementation(name: 'renderer-camera-release', ext: 'aar')
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/c_demo/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
11 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/c_demo/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 |
4 | android {
5 | compileSdkVersion 30
6 |
7 | defaultConfig {
8 | applicationId 'co.polarr.renderdemoclib'
9 | minSdkVersion 17
10 | targetSdkVersion 30
11 | ndk {
12 | abiFilters 'arm64-v8a'//,'arm64-v8a', 'x86'
13 | }
14 | externalNativeBuild {
15 | cmake {
16 | arguments '-DANDROID_TOOLCHAIN=clang', '-DANDROID_STL=c++_static'
17 | }
18 | }
19 | }
20 | buildTypes {
21 | release {
22 | minifyEnabled = false
23 | proguardFiles getDefaultProguardFile('proguard-android.txt'),
24 | 'proguard-rules.pro'
25 | }
26 | }
27 | externalNativeBuild {
28 | cmake {
29 | path 'src/main/cpp/CMakeLists.txt'
30 | }
31 | }
32 | sourceSets {
33 | main {
34 | jniLibs.srcDirs = ["src/main/cpp/jnis"]
35 | }
36 | }
37 | ndkVersion '22.1.7171670'
38 | }
39 |
--------------------------------------------------------------------------------
/java_demo/src/main/java/co/polarr/polarrcamerademo/OESTexture.java:
--------------------------------------------------------------------------------
1 | package co.polarr.polarrcamerademo;
2 |
3 | import android.opengl.GLES11Ext;
4 | import android.opengl.GLES20;
5 |
6 | public class OESTexture {
7 | private int mTextureHandle;
8 |
9 | public int getTextureId() {
10 | return mTextureHandle;
11 | }
12 |
13 | public void init() {
14 | int[] mTextureHandles = new int[1];
15 | GLES20.glGenTextures(1, mTextureHandles, 0);
16 | mTextureHandle = mTextureHandles[0];
17 |
18 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mTextureHandles[0]);
19 | GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
20 | GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
21 | GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
22 | GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
23 | }
24 |
25 | }
--------------------------------------------------------------------------------
/c_demo/src/main/java/co/polarr/render/PolarrRenderJni.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package co.polarr.render;
18 |
19 | // Wrapper for native library
20 |
21 | public class PolarrRenderJni {
22 |
23 | static {
24 | System.loadLibrary("PolarrRenderJNI");
25 | }
26 |
27 | public static native void init(int width, int height, int stride, int scanline, boolean needEgl);
28 |
29 | public static native void release();
30 |
31 | public static native byte[] updateYUVData(byte[] yuvArr);
32 | }
33 |
--------------------------------------------------------------------------------
/java_demo/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
18 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/c_demo/src/main/cpp/include/polarrRender.h:
--------------------------------------------------------------------------------
1 | #ifndef POLARR_RENDER_H
2 | #define POLARR_RENDER_H 1
3 |
4 | #define POLARR_SDK_VERSION "1.1.1_b16"
5 |
6 | enum INPUT_YUV_TYPE {
7 | INPUT_YUV_TYPE_NV21,
8 | INPUT_YUV_TYPE_NV12,
9 | INPUT_YUV_TYPE_YV12
10 | };
11 |
12 | enum POLARR_FILTER {
13 | F_COMMON_1,// 和风抹茶
14 | F_COMMON_2,// 秋天童话
15 | F_COMMON_3,// 青柠奶泡
16 | F_COMMON_4,// 海盐泡芙
17 | F_COMMON_5,// 黑咖啡
18 | F_COMMON_6,// 奇幻城堡
19 | F_FRONT_1,// 西柚冰沙
20 | F_FRONT_2,// 蓝莓松饼
21 | F_FRONT_3,// 雪域芝士
22 | F_FRONT_4,// 浆果奶酪
23 | F_FRONT_5,// 奶油慕斯
24 | F_BACK_1,// 花样年华
25 | F_BACK_2,// 情书
26 | F_BACK_3,// 2046
27 | F_BACK_4,// 莓果布丁
28 | F_BACK_5,// 重庆森林
29 | F_MODE_1, //模式1
30 | F_MODE_2, //模式2
31 | F_MODE_3, //模式3
32 | F_MODE_4, //模式4
33 | F_DEFAULT // 无滤镜
34 | };
35 |
36 | class RenderInternal;
37 |
38 | class PolarrRender {
39 | public:
40 | PolarrRender();
41 |
42 | virtual ~PolarrRender();
43 |
44 | void init(bool needEgl);
45 |
46 | void setYUVsize(int width, int height,
47 | int stride, int scanline, INPUT_YUV_TYPE yuvType);
48 |
49 | void initFilter(POLARR_FILTER filterType);
50 |
51 | void applyFilter(unsigned char *inputBytes, INPUT_YUV_TYPE yuvType);
52 |
53 | void applyFilterYUV(unsigned char *yBytes, unsigned char *uvBytes, INPUT_YUV_TYPE yuvType);
54 |
55 | private:
56 | RenderInternal *params;
57 | };
58 |
59 | #endif // POLARR_RENDER_H
60 |
--------------------------------------------------------------------------------
/java_demo/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
10 |
11 |
18 |
19 |
24 |
25 |
30 |
31 |
32 |
33 |
41 |
42 |
--------------------------------------------------------------------------------
/c_demo/README_zh.md:
--------------------------------------------------------------------------------
1 | # 泼辣滤镜Camera SDK C++版本
2 | ## 版权限制
3 | 包含本SDK在内的所有版本库中的内容,属于Polarr, Inc.版权所有。未经允许均不得用于商业目的。如需要获取完整授权等更多相关信息,请联系我们[info@polarr.co](mailto:info@polarr.co)
4 |
5 | ## 增加头文件
6 | ```objectivec
7 | #include "polarrRender.h"
8 | ```
9 | ## 初始化 PolarrRender
10 | 如果在非OpenGL环境下调用,请将needEgl参数设置为true。
11 | ```objectivec
12 | polarrRender = new PolarrRender;
13 | bool needEgl;
14 | polarrRender->init(needEgl);
15 | ```
16 | ## 设置YUV尺寸
17 | ```objectivec
18 | INPUT_YUV_TYPE yuvType = INPUT_YUV_TYPE_NV12;
19 | polarrRender->setYUVsize(width, height, stride, scanline, yuvType);
20 | ```
21 | ## 滤镜
22 | ### 滤镜列表
23 | 参考头文件中的内置滤镜
24 | ```objectivec
25 | enum POLARR_FILTER {
26 | F_COMMON_1,// 和风抹茶
27 | F_COMMON_2,// 秋天童话
28 | F_COMMON_3,// 青柠奶泡
29 | F_COMMON_4,// 海盐泡芙
30 | F_COMMON_5,// 黑咖啡
31 | F_COMMON_6,// 奇幻城堡
32 | F_FRONT_1,// 西柚冰沙
33 | F_FRONT_2,// 蓝莓松饼
34 | F_FRONT_3,// 雪域芝士
35 | F_FRONT_4,// 浆果奶酪
36 | F_FRONT_5,// 奶油慕斯
37 | F_BACK_1,// 花样年华
38 | F_BACK_2,// 情书
39 | F_BACK_3,// 2046
40 | F_BACK_4,// 莓果布丁
41 | F_BACK_5,// 重庆森林
42 | F_MODE_1, //模式1
43 | F_MODE_2, //模式2
44 | F_MODE_3, //模式3
45 | F_MODE_4, //模式4
46 | F_DEFAULT // 无滤镜
47 | };
48 | ```
49 | ### 设置滤镜
50 | ```objectivec
51 | polarrRender->initFilter(F_COMMON_1);
52 | ```
53 | ### 应用滤镜(连续的YUV数据)
54 | 该接口将复用输入数组
55 | ```objectivec
56 | INPUT_YUV_TYPE yuvType = INPUT_YUV_TYPE_NV21;
57 | polarrRender->applyFilter(yuvBytes, yuvType);
58 | ```
59 | ### 应用滤镜(分离的Y、UV数据)
60 | 该接口将复用输入数组
61 | ```objectivec
62 | INPUT_YUV_TYPE yuvType = INPUT_YUV_TYPE_NV12;
63 | polarrRender->applyFilterYUV(yBytes, uvBytes, yuvType);
64 | ```
65 | ### 支持的YUV格式
66 | ```objectivec
67 | enum INPUT_YUV_TYPE {
68 | INPUT_YUV_TYPE_NV21, // YUV420 NV21
69 | INPUT_YUV_TYPE_NV12, // YUV420 NV12
70 | INPUT_YUV_TYPE_YV12 // YV12
71 | };
72 | ```
73 | ## 释放资源
74 | ```objectivec
75 | delete polarrRender;
76 | ```
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ### Android ###
2 | # Built application files
3 | *.apk
4 | *.ap_
5 | .DS_Store
6 |
7 | # Files for the Dalvik VM
8 | *.dex
9 |
10 | # Java class files
11 | *.class
12 |
13 | # Generated files
14 | bin/
15 | gen/
16 |
17 | # Gradle files
18 | .gradle/
19 | build/
20 |
21 | # Local configuration file (sdk path, etc)
22 | local.properties
23 |
24 | # Proguard folder generated by Eclipse
25 | proguard/
26 |
27 | # Log Files
28 | *.log
29 |
30 | # Android Studio Navigation editor temp files
31 | .navigation/
32 |
33 | ### Android Patch ###
34 | gen-external-apklibs
35 |
36 |
37 | ### Java ###
38 | *.class
39 |
40 | # Mobile Tools for Java (J2ME)
41 | .mtj.tmp/
42 |
43 | # Package Files #
44 | #*.jar
45 | *.war
46 | *.ear
47 |
48 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
49 | hs_err_pid*
50 |
51 |
52 | ### Intellij ###
53 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio
54 |
55 | *.iml
56 |
57 | ## Directory-based project format:
58 | .idea/
59 | # if you remove the above rule, at least ignore the following:
60 |
61 | # User-specific stuff:
62 | # .idea/workspace.xml
63 | # .idea/tasks.xml
64 | # .idea/dictionaries
65 |
66 | # Sensitive or high-churn files:
67 | # .idea/dataSources.ids
68 | # .idea/dataSources.xml
69 | # .idea/sqlDataSources.xml
70 | # .idea/dynamic.xml
71 | # .idea/uiDesigner.xml
72 |
73 | # Gradle:
74 | # .idea/gradle.xml
75 | # .idea/libraries
76 |
77 | # Mongo Explorer plugin:
78 | # .idea/mongoSettings.xml
79 |
80 | ## File-based project format:
81 | *.ipr
82 | *.iws
83 |
84 | ## Plugin-specific files:
85 |
86 | # IntelliJ
87 | /out/
88 | /captures
89 |
90 | # mpeltonen/sbt-idea plugin
91 | .idea_modules/
92 |
93 | # JIRA plugin
94 | atlassian-ide-plugin.xml
95 |
96 | # Crashlytics plugin (for Android Studio and IntelliJ)
97 | com_crashlytics_export_strings.xml
98 | crashlytics.properties
99 | crashlytics-build.properties
100 |
--------------------------------------------------------------------------------
/c_demo/README.md:
--------------------------------------------------------------------------------
1 | # Polarr Camera SDK C++ Version
2 | ## License
3 | The SDK included in this repository must not be used for any commercial purposes without the direct written consent of Polarr, Inc. The current version of the SDK expires on December 31, 2021. For pricing and more info regarding the full license SDK, please email [hello@polarr.ai](mailto:hello@polarr.ai).
4 |
5 | ## Include header
6 | ```objectivec
7 | #include "polarrRender.h"
8 | ```
9 | ## Initialize PolarrRender
10 | If method is called outside an OpenGL environment, then please set needEgl to be true.
11 | ```objectivec
12 | polarrRender = new PolarrRender;
13 | bool needEgl;
14 | polarrRender->init(needEgl);
15 | ```
16 | ## Set YUV dimensions
17 | ```objectivec
18 | polarrRender->setYUVsize(width, height, stride, scanline);
19 | ```
20 | ## Filters
21 | ### Filter packs
22 | Refer to the header file for list of included filters
23 | ```objectivec
24 | enum POLARR_FILTER {
25 | F_COMMON_1,// Japan
26 | F_COMMON_2,// Nature
27 | F_COMMON_3,// Clear
28 | F_COMMON_4,// Clay
29 | F_COMMON_5,// B&W
30 | F_COMMON_6,// M1
31 | F_FRONT_1,// Icy
32 | F_FRONT_2,// Lagoon
33 | F_FRONT_3,// Paris 10
34 | F_FRONT_4,// T2
35 | F_FRONT_5,// Muse
36 | F_BACK_1,// M3
37 | F_BACK_2,// T1
38 | F_BACK_3,// C1
39 | F_BACK_4,// Electric
40 | F_BACK_5,// S109
41 | F_MODE_1, //M1
42 | F_MODE_2, //M2
43 | F_MODE_3, //M3
44 | F_MODE_4, //M4
45 | F_DEFAULT //No filter
46 | };
47 | ```
48 | ### Set filter
49 | ```objectivec
50 | polarrRender->initFilter(F_COMMON_1);
51 | ```
52 | ### Apply filter via YUV format
53 | This interface will reuse the input parameter, YUV format is YUV420 NV21
54 | ```objectivec
55 | polarrRender->applyFilter(yuvBytes);
56 | ```
57 | ### Apply filter via separate Y and UV parameters
58 | This interface will reuse the input parameter, YUV format is YUV420 NV21
59 | ```objectivec
60 | polarrRender->applyFilterYUV(yBytes, uvBytes);
61 | ```
62 | ## Release resources
63 | ```objectivec
64 | delete polarrRender;
65 | ```
66 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/c_demo/src/main/cpp/polarrRenderJni.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Colin PRO on 2017/12/12.
3 | //
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 |
13 | #include "polarrRender.h"
14 |
15 | #define LOG_TAG "POLARR_JNI"
16 | #define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
17 |
18 | PolarrRender *polarrRender;
19 |
20 | unsigned char *as_unsigned_char_array(JNIEnv *env, jbyteArray array) {
21 | int len = env->GetArrayLength(array);
22 | unsigned char *buf = new unsigned char[len];
23 | env->GetByteArrayRegion(array, 0, len, reinterpret_cast(buf));
24 |
25 | return buf;
26 | }
27 |
28 | jbyteArray as_byte_array(JNIEnv *env, unsigned char *buf, int len) {
29 | jbyteArray array = env->NewByteArray(len);
30 | env->SetByteArrayRegion(array, 0, len, reinterpret_cast(buf));
31 | return array;
32 | }
33 |
34 | long long currentTimeInMilliseconds() {
35 | struct timeval tv;
36 | gettimeofday(&tv, NULL);
37 | return ((tv.tv_sec * 1000) + (tv.tv_usec / 1000));
38 | }
39 |
40 | extern "C"
41 | JNIEXPORT void JNICALL
42 | Java_co_polarr_render_PolarrRenderJni_init(JNIEnv *env, jclass type,
43 | jint width, jint height, jint stride, jint scanline,
44 | jboolean needEgl) {
45 | polarrRender = new PolarrRender;
46 |
47 | long during;
48 | long long startTime;
49 |
50 | startTime = currentTimeInMilliseconds();
51 |
52 | polarrRender->init(needEgl);
53 | polarrRender->setYUVsize(width, height, stride, scanline, INPUT_YUV_TYPE_NV21);
54 |
55 | during = currentTimeInMilliseconds() - startTime;
56 |
57 | ALOGD("Init sdk:%"
58 | PRId64
59 | "ms", during);
60 |
61 |
62 | }
63 |
64 | extern "C"
65 | JNIEXPORT void JNICALL
66 | Java_co_polarr_render_PolarrRenderJni_release(JNIEnv *env, jclass type) {
67 | delete polarrRender;
68 | }
69 |
70 | extern "C"
71 | JNIEXPORT jbyteArray JNICALL
72 | Java_co_polarr_render_PolarrRenderJni_updateYUVData(JNIEnv *env, jclass type,
73 | jbyteArray yuvArr) {
74 | int len = env->GetArrayLength(yuvArr);
75 | unsigned char *yuvBytes = as_unsigned_char_array(env, yuvArr);
76 |
77 | // int size = len * 2 / 3;
78 | // u_char *yBytes = (u_char *) malloc(sizeof(u_char) * size);
79 | // u_char *uvBytes = (u_char *) malloc(sizeof(u_char) * size / 2);
80 | // memcpy(yBytes, yuvBytes, sizeof(u_char) * size);
81 | // memcpy(uvBytes, yuvBytes + size, sizeof(u_char) * size / 2);
82 |
83 | long during;
84 | long long startTime;
85 |
86 | startTime = currentTimeInMilliseconds();
87 |
88 | polarrRender->initFilter(F_COMMON_5);
89 |
90 | during = currentTimeInMilliseconds() - startTime;
91 |
92 | ALOGD("Init filter & size:%"
93 | PRId64
94 | "ms", during);
95 |
96 | startTime = currentTimeInMilliseconds();
97 |
98 | polarrRender->applyFilter(yuvBytes, INPUT_YUV_TYPE_NV21);
99 | during = currentTimeInMilliseconds() - startTime;
100 | ALOGD("APPLY FILTER:%"
101 | PRId64
102 | "ms", during);
103 |
104 |
105 | // memcpy(yuvBytes, yBytes, sizeof(u_char) * size);
106 | // memcpy(yuvBytes + size, uvBytes, sizeof(u_char) * size / 2);
107 | //
108 | //
109 | // delete yBytes;
110 | // delete uvBytes;
111 |
112 | return as_byte_array(env, yuvBytes, len);
113 | }
114 |
--------------------------------------------------------------------------------
/java_demo/README_zh.md:
--------------------------------------------------------------------------------
1 | # 泼辣滤镜Camera SDK Java版版本
2 | ## 版权限制
3 | 包含本SDK在内的所有版本库中的内容,属于Polarr, Inc.版权所有。未经允许均不得用于商业目的。当前版本的示例SDK失效时间为2024年12月31日。如需要获取完整授权等更多相关信息,请联系我们[info@polarr.co](mailto:info@polarr.co)
4 |
5 | ## 增加 dependencies 到 Gradle文件
6 | ```groovy
7 | // render sdk
8 | compile (name: 'renderer-camera-release', ext: 'aar')
9 | ```
10 | ## 在GL线程中初始化 PolarrRender
11 | ```java
12 | PolarrRender polarrRender = new PolarrRender();
13 |
14 | @Override
15 | public void onSurfaceCreated(GL10 gl, EGLConfig config) {
16 | // call in gl thread
17 | boolean fastMode = true; // true 为Camera应用优化
18 | int inputTextureType = PolarrRender.EXTERNAL_OES; // PolarrRender.TEXTURE_2D, PolarrRender.EXTERNAL_OES
19 | polarrRender.initRender(getResources(), getWidth(), getHeight(), fastMode, inputTextureType);
20 | }
21 | ```
22 | ## 创建或传入Texture
23 | ### 创建Texture
24 | ```java
25 | // 只需要调用一次
26 | polarrRender.createInputTexture();
27 | // bind a bitmap to sdk
28 | int inputTexture = polarrRender.getTextureId();
29 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, inputTexture);
30 | GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, bitmap, 0);
31 |
32 | // 输入Texture变化后需要调用
33 | polarrRender.updateInputTexture();
34 | ```
35 | ### 传入一个输入Texture
36 | ```java
37 | // 默认为GL_TEXTURE_2D格式
38 | polarrRender.setInputTexture(inputTexture);
39 | // 输入Texture变化后需要调用
40 | polarrRender.updateInputTexture();
41 | ```
42 | ## 设置输出Texture (非必须)
43 | 如果不设置输出Texture,SDK将会创建一个输出Texture。通过[获取输出的Texture](#获取输出的Texture)获取
44 | ```java
45 | // 必须为GL_TEXTURE_2D格式
46 | polarrRender.setOutputTexture(outputTexture);
47 | ```
48 | ## 更新渲染尺寸。更新后需要更新输入Texture
49 | ```java
50 | // call in gl thread
51 | polarrRender.updateSize(width, height);
52 | ```
53 | ## 渲染
54 | ```java
55 | @Override
56 | public void onDrawFrame(GL10 gl) {
57 | // call in GL thread
58 | polarrRender.drawFrame();
59 | }
60 | ```
61 | ## 渲染多个滤镜到Texture上
62 | ```java
63 | int gridOutputTexture; // 输出texture,不能和已经设置给polarrRender的output/input texture 相同
64 | List drawingItems; // 要渲染的滤镜id和位置
65 | DrawingItem.filterId; // 滤镜ID
66 | DrawingItem.rect; // 渲染到输出texture的位置
67 |
68 | polarrRender.drawFiltersFrame(drawingItems, gridOutputTexture);
69 | ```
70 | ## 获取输出的Texture
71 | ```java
72 | int out = polarrRender.getOutputId();
73 | ```
74 | ## 释放资源
75 | ```java
76 | // call in GL thread
77 | polarrRender.release();
78 | ```
79 | ## 滤镜工具
80 | SDK 内置了泼辣修图的滤镜包,滤镜包数据内置于renderer module中。
81 | ### 内置滤镜说明
82 | 通用系列
83 | ```java
84 | FilterPackageUtil.F_COMMON_1 // 和风抹茶
85 | FilterPackageUtil.F_COMMON_2 // 秋天童话
86 | FilterPackageUtil.F_COMMON_3 // 青柠奶泡
87 | FilterPackageUtil.F_COMMON_4 // 海盐泡芙
88 | FilterPackageUtil.F_COMMON_5 // 黑咖啡
89 | FilterPackageUtil.F_COMMON_6 // 奇幻城堡
90 | ```
91 | 前置系列
92 | ```java
93 | FilterPackageUtil.F_FRONT_1 // 西柚冰沙
94 | FilterPackageUtil.F_FRONT_2 // 蓝莓松饼
95 | FilterPackageUtil.F_FRONT_3 // 雪域芝士
96 | FilterPackageUtil.F_FRONT_4 // 浆果奶酪
97 | FilterPackageUtil.F_FRONT_5 // 奶油慕斯
98 | ```
99 | 后置系列
100 | ```java
101 | FilterPackageUtil.F_BACK_1 // 花样年华
102 | FilterPackageUtil.F_BACK_2 // 情书
103 | FilterPackageUtil.F_BACK_3 // 2046
104 | FilterPackageUtil.F_BACK_4 // 莓果布丁
105 | FilterPackageUtil.F_BACK_5 // 重庆森林
106 | ```
107 | 光效系列
108 | ```java
109 | FilterPackageUtil.F_MODE_1 // 模式1
110 | FilterPackageUtil.F_MODE_2 // 模式2
111 | FilterPackageUtil.F_MODE_3 // 模式3
112 | FilterPackageUtil.F_MODE_4 // 模式4
113 | ```
114 | 默认效果
115 | ```java
116 | FilterPackageUtil.F_DEFAULT
117 | ```
118 | ### 设置滤镜
119 | ```java
120 | polarrRender.fastUpdateFilter(filterId);
121 | ```
122 | ### 恢复默认效果
123 | ```java
124 | polarrRender.fastUpdateFilter(FilterPackageUtil.F_DEFAULT);
125 | ```
126 | ## 渲染相关工具
127 | ### 清除一个Texture
128 | 将Texture的全部区域的像素值设置为 RGBA(0,0,0,0)
129 | ```java
130 | polarrRender.clearTexture(texId, texWidth, texHeight);
131 | ```
132 | ## 获取版本号
133 | ```java
134 | String version = PolarrRender.Version();
135 | ```
--------------------------------------------------------------------------------
/java_demo/README.md:
--------------------------------------------------------------------------------
1 | # Polarr Camera SDK Java Version
2 | ## License
3 | The SDK included in this repository must not be used for any commercial purposes without the direct written consent of Polarr, Inc. The current version of the SDK expires on December 31, 2024. For pricing and more info regarding the full license SDK, please email [hello@polarr.ai](mailto:hello@polarr.ai).
4 |
5 | ## Add dependencies to the gradle files
6 | ```groovy
7 | // render sdk
8 | compile (name: 'renderer-camera-release', ext: 'aar')
9 | ```
10 | ## Initialize PolarrRender in the GL thread
11 | ```java
12 | PolarrRender polarrRender = new PolarrRender();
13 |
14 | @Override
15 | public void onSurfaceCreated(GL10 gl, EGLConfig config) {
16 | // call in gl thread
17 | boolean fastMode = true; // fast rendering
18 | int inputTextureType = PolarrRender.EXTERNAL_OES; // PolarrRender.TEXTURE_2D, PolarrRender.EXTERNAL_OES
19 | polarrRender.initRender(getResources(), getWidth(), getHeight(), fastMode, inputTextureType);
20 | }
21 | ```
22 | ## Create or pass in Texture
23 | ### Create Texture
24 | ```java
25 | // call this method only once
26 | polarrRender.createInputTexture();
27 | // bind a bitmap to sdk
28 | int inputTexture = polarrRender.getTextureId();
29 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, inputTexture);
30 | GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, bitmap, 0);
31 |
32 | // update Texture explicitly using the following method
33 | polarrRender.updateInputTexture();
34 | ```
35 | ### Pass in an input Texture
36 | ```java
37 | // default is GL_TEXTURE_2D
38 | polarrRender.setInputTexture(inputTexture);
39 | // update Texture explicitly using the following method
40 | polarrRender.updateInputTexture();
41 | ```
42 | ## Set up output Texture (optional)
43 | If you do not specify an output Texture, the SDK will create an output Texture. Using [Obtain output Texture](#Obtain output Texture) to acquire.
44 | ```java
45 | // Must be a GL_TEXTURE_2D
46 | polarrRender.setOutputTexture(outputTexture);
47 | ```
48 | ## Update the Texture size
49 | ```java
50 | // call in gl thread
51 | polarrRender.updateSize(width, height);
52 | ```
53 | ## Render
54 | ```java
55 | @Override
56 | public void onDrawFrame(GL10 gl) {
57 | // call in GL thread
58 | polarrRender.drawFrame();
59 | }
60 | ```
61 | ## Render multiple filters onto Texture
62 | ```java
63 | int gridOutputTexture; // output Texture,must be different from polarrRender output/input texture
64 | List drawingItems; // Need the filter id and rect to be rendered
65 | DrawingItem.filterId;
66 | DrawingItem.rect; // rendered to the specified rect
67 |
68 | polarrRender.drawFiltersFrame(drawingItems, gridOutputTexture);
69 | ```
70 | ## Obtain output Texture
71 | ```java
72 | int out = polarrRender.getOutputId();
73 | ```
74 | ## Release resources
75 | ```java
76 | // call in GL thread
77 | polarrRender.release();
78 | ```
79 | ## Filters
80 | SDK includes Polarr's proprietary filter packs, which are in side the renderer module.
81 | ### Filter descriptions
82 | General pack
83 | ```java
84 | FilterPackageUtil.F_COMMON_1 // Japan
85 | FilterPackageUtil.F_COMMON_2 // Nature
86 | FilterPackageUtil.F_COMMON_3 // Clear
87 | FilterPackageUtil.F_COMMON_4 // Clay
88 | FilterPackageUtil.F_COMMON_5 // Black & White
89 | FilterPackageUtil.F_COMMON_6 // M1
90 | ```
91 | Front pack
92 | ```java
93 | FilterPackageUtil.F_FRONT_1 // Icy
94 | FilterPackageUtil.F_FRONT_2 // Lagoon
95 | FilterPackageUtil.F_FRONT_3 // Paris 10
96 | FilterPackageUtil.F_FRONT_4 // T2
97 | FilterPackageUtil.F_FRONT_5 // Muse
98 | ```
99 | Back pack
100 | ```java
101 | FilterPackageUtil.F_BACK_1 // M3
102 | FilterPackageUtil.F_BACK_2 // T1
103 | FilterPackageUtil.F_BACK_3 // C1
104 | FilterPackageUtil.F_BACK_4 // Electric
105 | FilterPackageUtil.F_BACK_5 // S109
106 | ```
107 | Light pack
108 | ```java
109 | FilterPackageUtil.F_MODE_1 // M1
110 | FilterPackageUtil.F_MODE_2 // M2
111 | FilterPackageUtil.F_MODE_3 // M3
112 | FilterPackageUtil.F_MODE_4 // M4
113 | ```
114 | Default effect
115 | ```java
116 | FilterPackageUtil.F_DEFAULT
117 | ```
118 | ### Set filter
119 | ```java
120 | polarrRender.fastUpdateFilter(filterId);
121 | ```
122 | ### Reset to default filter
123 | ```java
124 | polarrRender.fastUpdateFilter(FilterPackageUtil.F_DEFAULT);
125 | ```
126 | ## Get the version
127 | ```java
128 | String version = PolarrRender.Version();
129 | ```
130 |
--------------------------------------------------------------------------------
/java_demo/src/main/java/co/polarr/polarrcamerademo/FaceUtil.java:
--------------------------------------------------------------------------------
1 | package co.polarr.polarrcamerademo;
2 |
3 | import android.graphics.Point;
4 | import android.graphics.PointF;
5 | import android.graphics.Rect;
6 |
7 | import java.util.ArrayList;
8 | import java.util.HashMap;
9 | import java.util.List;
10 | import java.util.Map;
11 |
12 | import co.polarr.renderer.entities.FaceItem;
13 |
14 | /**
15 | * Created by Colin on 2017/12/2.
16 | */
17 |
18 | public class FaceUtil {
19 | /**
20 | * get the face features with 106 points input
21 | */
22 | public static Map GetFaceFeaturesWithPoints(List> facePoints, int imageWidth, int imageHeight) {
23 | Map faces = new HashMap<>();
24 |
25 | if (facePoints == null) {
26 | return faces;
27 | }
28 |
29 | List faceDetResults = new ArrayList<>();
30 | for (List points : facePoints) {
31 | if (points.size() == 106) {
32 | faceDetResults.add(mapSenstimeToDlib(points));
33 | }
34 | }
35 |
36 | faces = createFaceStates(faceDetResults, imageWidth, imageHeight);
37 |
38 |
39 | return faces;
40 | }
41 |
42 | private static Map createFaceStates(List faceDetResults, int bitmapWidth, int bitmapHeight) {
43 | Map faceStates = new HashMap<>();
44 | List faces = new ArrayList<>();
45 | List faceFeatures = new ArrayList<>();
46 |
47 | faceStates.put("faces", faces);
48 | faceStates.put("face_features", faceFeatures);
49 |
50 | for (FaceDetResult faceDetResult : faceDetResults) {
51 | FaceItem faceItem = new FaceItem();
52 | List markArray = faceDetResult.points;
53 | float keyPoints[][] = new float[markArray.size()][];
54 | for (int i = 0; i < markArray.size(); i++) {
55 | Point point = markArray.get(i);
56 | keyPoints[i] = new float[]{
57 | point.x / (float) bitmapWidth,
58 | point.y / (float) bitmapHeight,
59 | };
60 | }
61 | faceItem.markers = keyPoints;
62 | faceItem.boundaries = new float[]{
63 | faceDetResult.rect.left / (float) bitmapWidth,
64 | faceDetResult.rect.top / (float) bitmapHeight,
65 | faceDetResult.rect.width() / (float) bitmapWidth,
66 | faceDetResult.rect.height() / (float) bitmapHeight
67 | };
68 | faces.add(faceItem);
69 |
70 | faceFeatures.add(new co.polarr.renderer.entities.Context.FaceFeaturesState());
71 | }
72 |
73 | return faceStates;
74 | }
75 |
76 | // senstime 106 points to dlib 68 points
77 | private static FaceDetResult mapSenstimeToDlib(List points) {
78 | FaceDetResult faceDetResult = new FaceDetResult();
79 | // face edge
80 | for (int i = 0; i <= 32; i += 2) {
81 | PointF srcPoint = points.get(i / 2);
82 | Point point = new Point(Math.round(srcPoint.x), Math.round(srcPoint.y));
83 | faceDetResult.points.add(point);
84 | }
85 |
86 | // eyebrows,nose,eyes
87 | for (int i = 33; i <= 63; i += 1) {
88 | PointF srcPoint = points.get(i);
89 | Point point = new Point(Math.round(srcPoint.x), Math.round(srcPoint.y));
90 | faceDetResult.points.add(point);
91 | }
92 |
93 | // mouth
94 | for (int i = 84; i <= 103; i += 1) {
95 | PointF srcPoint = points.get(i);
96 | Point point = new Point(Math.round(srcPoint.x), Math.round(srcPoint.y));
97 | faceDetResult.points.add(point);
98 | }
99 |
100 | faceDetResult.rect = getFaceRect(faceDetResult.points);
101 | return faceDetResult;
102 | }
103 |
104 | private static Rect getFaceRect(List points) {
105 | Rect rect = new Rect();
106 |
107 | rect.left = points.get(0).x;
108 | rect.bottom = points.get(8).y;
109 | rect.right = points.get(16).x;
110 | rect.top = centerPoint(points.get(19), points.get(24)).y;
111 |
112 | return rect;
113 | }
114 |
115 | private static Point centerPoint(Point... points) {
116 | Point center = new Point();
117 | int totalX = 0, totalY = 0;
118 | if (points != null) {
119 | for (Point point : points) {
120 | totalX += point.x;
121 | totalY += point.y;
122 | }
123 |
124 | center.x = totalX / points.length;
125 | center.y = totalY / points.length;
126 | }
127 |
128 |
129 | return center;
130 | }
131 |
132 | private static class FaceDetResult {
133 | List points = new ArrayList<>();
134 | Rect rect = new Rect();
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/c_demo/src/main/java/co/polarr/renderdemoclib/MainActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package co.polarr.renderdemoclib;
18 |
19 | import android.app.Activity;
20 | import android.content.Context;
21 | import android.graphics.Bitmap;
22 | import android.graphics.Matrix;
23 | import android.os.Bundle;
24 | import android.renderscript.Allocation;
25 | import android.renderscript.Element;
26 | import android.renderscript.RenderScript;
27 | import android.renderscript.ScriptIntrinsicYuvToRGB;
28 | import android.renderscript.Type;
29 | import android.widget.ImageView;
30 |
31 | import java.io.IOException;
32 | import java.io.InputStream;
33 |
34 | import co.polarr.render.PolarrRenderJni;
35 |
36 | public class MainActivity extends Activity {
37 | private ImageView imageView;
38 |
39 | private int w = 0;
40 | private int h = 0;
41 | private int stride = 0;
42 | private int scanline = 0;
43 | private byte[] yuvData;
44 |
45 | @Override
46 | protected void onCreate(Bundle icicle) {
47 | super.onCreate(icicle);
48 | setContentView(R.layout.activity_fullscreen);
49 |
50 | imageView = (ImageView) findViewById(R.id.imageView);
51 |
52 | new Thread() {
53 | @Override
54 | public void run() {
55 | prepareYUVDemoData(getApplicationContext(), 0);
56 | // showYuv(yuvData);
57 | PolarrRenderJni.init(w, h, stride, scanline, true);
58 | yuvData = PolarrRenderJni.updateYUVData(yuvData);
59 | PolarrRenderJni.release();
60 |
61 | showYuv(yuvData);
62 | }
63 | }.start();
64 | }
65 |
66 | @Override
67 | protected void onPause() {
68 | super.onPause();
69 | }
70 |
71 | @Override
72 | protected void onResume() {
73 | super.onResume();
74 | }
75 |
76 |
77 | private void prepareYUVDemoData(Context context, int demoIndex) {
78 | String fileName = "";
79 | switch (demoIndex) {
80 | case 0: {
81 | fileName = "yuv.dat";
82 | w = 960;
83 | h = 720;
84 | stride = 960;
85 | scanline = 720;
86 | }
87 | break;
88 | case 1: {
89 | fileName = "2970group_4608x3456_idx72_master.yuv";
90 | w = 4608;
91 | h = 3456;
92 | stride = 4608;
93 | scanline = 3456;
94 | }
95 | break;
96 | case 2: {
97 | fileName = "2952group_1856x1408_idx48_slave.yuv";
98 | w = 1840;
99 | h = 1380;
100 | stride = 1856;
101 | scanline = 1408;
102 | }
103 | break;
104 | case 3: {
105 | fileName = "2952group_3264x2496_idx48_master.yuv";
106 | w = 3264;
107 | h = 2448;
108 | stride = 3264;
109 | scanline = 2496;
110 | }
111 | break;
112 | case 4: {
113 | fileName = "2970group_2624x1984_idx72_slave.yuv";
114 | w = 2592;
115 | h = 1940;
116 | stride = 2624;
117 | scanline = 1984;
118 | }
119 | break;
120 | case 5: {
121 | fileName = "IMG20180101001748_2624x1984_filter_in_id131.yuv";
122 | w = 2592;
123 | h = 1940;
124 | stride = 2624;
125 | scanline = 1984;
126 | }
127 | case 6: {
128 | fileName = "IMG20180101001748_2624x1984_filter_in_id131.yuv";
129 | w = 1280;
130 | h = 720;
131 | stride = 1280;
132 | scanline = 720;
133 | }
134 | break;
135 | }
136 |
137 | yuvData = new byte[stride * scanline * 3 / 2];
138 | try {
139 | InputStream is = context.getAssets().open(fileName);
140 | is.read(yuvData);
141 | is.close();
142 | } catch (IOException e) {
143 | System.out.println("IoException:" + e.getMessage());
144 | e.printStackTrace();
145 | }
146 | }
147 |
148 | private void showYuv(byte[] yuvData) {
149 | Allocation bmData = null;
150 | bmData = renderScriptNV21ToRGBA888(
151 | this,
152 | stride,
153 | scanline,
154 | yuvData);
155 |
156 | Bitmap stitchBmp = Bitmap.createBitmap(stride, scanline, Bitmap.Config.ARGB_8888);
157 | bmData.copyTo(stitchBmp);
158 |
159 | // stitchBmp = getRotatedImage(stitchBmp, 90);
160 | final Bitmap finalStitchBmp = stitchBmp;
161 | runOnUiThread(new Runnable() {
162 | @Override
163 | public void run() {
164 | imageView.setImageBitmap(finalStitchBmp);
165 | }
166 | });
167 | }
168 |
169 | public Allocation renderScriptNV21ToRGBA888(Context context, int width, int height, byte[] nv21) {
170 | RenderScript rs = RenderScript.create(context);
171 | ScriptIntrinsicYuvToRGB yuvToRgbIntrinsic = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs));
172 |
173 | Type.Builder yuvType = new Type.Builder(rs, Element.U8(rs)).setX(nv21.length);
174 | Allocation in = Allocation.createTyped(rs, yuvType.create(), Allocation.USAGE_SCRIPT);
175 |
176 | Type.Builder rgbaType = new Type.Builder(rs, Element.RGBA_8888(rs)).setX(width).setY(height);
177 | Allocation out = Allocation.createTyped(rs, rgbaType.create(), Allocation.USAGE_SCRIPT);
178 |
179 | in.copyFrom(nv21);
180 |
181 | yuvToRgbIntrinsic.setInput(in);
182 | yuvToRgbIntrinsic.forEach(out);
183 | return out;
184 | }
185 |
186 | private static Bitmap getRotatedImage(Bitmap bitmap, int degrees) {
187 | if (bitmap != null && degrees != 0) {
188 | int w = bitmap.getWidth();
189 | int h = bitmap.getHeight();
190 | Matrix m = new Matrix();
191 | m.postRotate(degrees, w / 2, h / 2);
192 | Bitmap bm = Bitmap.createBitmap(bitmap, 0, 0, w, h, m, true);
193 | if (bm != bitmap) {
194 | bitmap.recycle();
195 | }
196 | bitmap = bm;
197 | }
198 |
199 | return bitmap;
200 | }
201 | }
202 |
--------------------------------------------------------------------------------
/java_demo/src/main/java/co/polarr/polarrcamerademo/MainActivity.java:
--------------------------------------------------------------------------------
1 | package co.polarr.polarrcamerademo;
2 |
3 | import android.Manifest;
4 | import android.app.Activity;
5 | import android.content.DialogInterface;
6 | import android.content.Intent;
7 | import android.content.pm.PackageManager;
8 | import android.graphics.Bitmap;
9 | import android.net.Uri;
10 | import android.os.Bundle;
11 | import android.os.Environment;
12 | import androidx.annotation.NonNull;
13 | import androidx.appcompat.app.AlertDialog;
14 | import androidx.core.app.ActivityCompat;
15 | import androidx.core.content.ContextCompat;
16 | import android.view.View;
17 | import android.view.Window;
18 | import android.view.WindowManager;
19 | import android.widget.Button;
20 | import android.widget.Toast;
21 |
22 | import java.io.File;
23 | import java.io.FileNotFoundException;
24 | import java.io.FileOutputStream;
25 | import java.io.OutputStream;
26 | import java.text.SimpleDateFormat;
27 | import java.util.ArrayList;
28 | import java.util.Date;
29 | import java.util.List;
30 |
31 | import co.polarr.renderer.FilterPackageUtil;
32 | import co.polarr.renderer.entities.FilterItem;
33 | import co.polarr.renderer.entities.FilterPackage;
34 |
35 |
36 | public class MainActivity extends Activity {
37 | private static final int REQUEST_CAMERA_PERMISSION = 1;
38 | private static final int REQUEST_STORAGE_PERMISSION = 2;
39 |
40 |
41 | private CameraRenderView mRenderer;
42 | private List mFilters;
43 | private String currentFilterName = "无滤镜";
44 |
45 | @Override
46 | protected void onCreate(Bundle savedInstanceState) {
47 | super.onCreate(savedInstanceState);
48 | requestWindowFeature(Window.FEATURE_NO_TITLE);
49 | getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
50 | WindowManager.LayoutParams.FLAG_FULLSCREEN);
51 |
52 | setContentView(R.layout.activity_main);
53 | mRenderer = (CameraRenderView) findViewById(R.id.renderer_view);
54 |
55 | if (!checkAndRequirePermission(REQUEST_CAMERA_PERMISSION)) {
56 | mRenderer.setVisibility(View.INVISIBLE);
57 | }
58 |
59 | findViewById(R.id.btn_photo).setOnClickListener(new View.OnClickListener() {
60 | @Override
61 | public void onClick(View v) {
62 | if (checkAndRequirePermission(REQUEST_STORAGE_PERMISSION)) {
63 | takePhoto();
64 | }
65 | }
66 | });
67 |
68 | List packages = FilterPackageUtil.GetAllFilters(getResources());
69 | mFilters = new ArrayList<>();
70 | for (FilterPackage filterPackage : packages) {
71 | mFilters.addAll(filterPackage.filters);
72 | }
73 |
74 | final Button btnFilters = (Button) findViewById(R.id.btn_filters);
75 | btnFilters.setOnClickListener(new View.OnClickListener() {
76 | @Override
77 | public void onClick(View v) {
78 | AlertDialog.Builder adb = new AlertDialog.Builder(MainActivity.this, R.style.MyDialogTheme);
79 | final CharSequence items[] = new CharSequence[mFilters.size()];
80 | for (int i = 0; i < mFilters.size(); i++) {
81 | items[i] = mFilters.get(i).filterName("zh");
82 | }
83 | adb.setItems(items, new DialogInterface.OnClickListener() {
84 |
85 | @Override
86 | public void onClick(DialogInterface dialog, int n) {
87 | FilterItem filterItem = mFilters.get(n);
88 |
89 | mRenderer.updateFilter(filterItem.id);
90 |
91 | currentFilterName = items[n].toString();
92 | btnFilters.setText(currentFilterName);
93 | }
94 |
95 | });
96 | adb.setNegativeButton("Cancel", null);
97 | adb.setTitle("Choose a filter:");
98 | adb.show();
99 | }
100 | });
101 |
102 | findViewById(R.id.btn_random_9).setOnClickListener(new View.OnClickListener() {
103 | @Override
104 | public void onClick(View v) {
105 | List testFilters = new ArrayList<>();
106 | if (mFilters.size() < 9) {
107 | for (FilterItem filterItem : mFilters) {
108 | testFilters.add(filterItem.id);
109 | }
110 | } else {
111 | while (testFilters.size() < 9) {
112 | FilterItem randomFilter = mFilters.get((int) (Math.random() * mFilters.size()));
113 | if (!testFilters.contains(randomFilter.id)) {
114 | testFilters.add(randomFilter.id);
115 | }
116 | }
117 | }
118 |
119 | mRenderer.setTestFilters(testFilters);
120 | }
121 | });
122 | }
123 |
124 |
125 | @Override
126 | public void onStart() {
127 | super.onStart();
128 | }
129 |
130 |
131 | @Override
132 | public void onPause() {
133 | super.onPause();
134 | mRenderer.onDestroy();
135 |
136 | }
137 |
138 | @Override
139 | public void onResume() {
140 | super.onResume();
141 | mRenderer.onResume();
142 | }
143 |
144 | private void takePhoto() {
145 | File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
146 | final File folder = new File(storageDir, "polarr_demo");
147 | if (!folder.exists()) {
148 | folder.mkdir();
149 | }
150 |
151 | mRenderer.takePhoto(new CameraRenderView.OnCaptureCallback() {
152 | @Override
153 | public void onPhoto(Bitmap bitmap) {
154 | String fileName = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
155 |
156 | final File outputFile = new File(folder.getPath(), fileName + "_" + currentFilterName + ".jpg");
157 | try {
158 | OutputStream fileOS = new FileOutputStream(outputFile);
159 | bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fileOS);
160 | runOnUiThread(new Runnable() {
161 | @Override
162 | public void run() {
163 | //Rescanning the icon_library/gallery so it catches up with our own changes
164 | Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
165 | mediaScanIntent.setData(Uri.fromFile(outputFile));
166 | sendBroadcast(mediaScanIntent);
167 |
168 | Toast.makeText(MainActivity.this, "Saved:" + outputFile.getPath(), Toast.LENGTH_LONG).show();
169 | }
170 | });
171 | } catch (FileNotFoundException e) {
172 | e.printStackTrace();
173 | }
174 | bitmap.recycle();
175 | }
176 | });
177 | }
178 |
179 | private boolean checkAndRequirePermission(int permissionRequestId) {
180 | String permission = Manifest.permission.READ_EXTERNAL_STORAGE;
181 | switch (permissionRequestId) {
182 | case REQUEST_CAMERA_PERMISSION:
183 | permission = Manifest.permission.CAMERA;
184 | break;
185 | case REQUEST_STORAGE_PERMISSION:
186 | permission = Manifest.permission.READ_EXTERNAL_STORAGE;
187 | break;
188 | }
189 | if (ContextCompat.checkSelfPermission(this, permission)
190 | != PackageManager.PERMISSION_GRANTED) {
191 |
192 | ActivityCompat.requestPermissions(this,
193 | new String[]{permission},
194 | permissionRequestId);
195 |
196 | return false;
197 | }
198 |
199 | return true;
200 | }
201 |
202 | @Override
203 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
204 | super.onRequestPermissionsResult(requestCode, permissions, grantResults);
205 | if (requestCode == REQUEST_CAMERA_PERMISSION && grantResults.length > 0) {
206 | if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
207 | mRenderer.setVisibility(View.VISIBLE);
208 | }
209 | } else if ((requestCode == REQUEST_STORAGE_PERMISSION) && grantResults.length > 0) {
210 | if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
211 | }
212 | }
213 | }
214 |
215 | }
--------------------------------------------------------------------------------
/java_demo/src/main/java/co/polarr/polarrcamerademo/CameraRenderView.java:
--------------------------------------------------------------------------------
1 | package co.polarr.polarrcamerademo;
2 |
3 | import android.content.Context;
4 | import android.content.res.Configuration;
5 | import android.graphics.Bitmap;
6 | import android.graphics.BitmapFactory;
7 | import android.graphics.Canvas;
8 | import android.graphics.Paint;
9 | import android.graphics.PixelFormat;
10 | import android.graphics.Rect;
11 | import android.graphics.SurfaceTexture;
12 | import android.hardware.Camera;
13 | import android.opengl.GLES20;
14 | import android.opengl.GLSurfaceView;
15 | import android.opengl.GLUtils;
16 | import android.opengl.Matrix;
17 | import android.util.AttributeSet;
18 | import android.util.Log;
19 | import android.view.Surface;
20 |
21 | import java.io.IOException;
22 | import java.nio.ByteBuffer;
23 | import java.util.ArrayList;
24 | import java.util.Arrays;
25 | import java.util.List;
26 | import java.util.Locale;
27 |
28 | import javax.microedition.khronos.egl.EGLConfig;
29 | import javax.microedition.khronos.opengles.GL10;
30 |
31 | import co.polarr.renderer.PolarrRender;
32 | import co.polarr.renderer.entities.DrawingItem;
33 | import co.polarr.renderer.filters.Basic;
34 |
35 | /**
36 | * Created by Colin on 2017/11/18.
37 | * Camera Demo
38 | */
39 |
40 | public class CameraRenderView extends GLSurfaceView implements GLSurfaceView.Renderer, SurfaceTexture.OnFrameAvailableListener {
41 | private static final int GRID_SIZE = 3;
42 | private static final int GRID_WIDTH = 320;
43 | private static final int GRID_HEIGHT = 480;
44 | private static final boolean DEBUG_DEMO_TEXTURE2D_INPUT = false;
45 | private static final boolean DEBUG_DEMO_OES_INPUT = !true;
46 | private Context mContext;
47 |
48 | /**
49 | * Camera and SurfaceTexture
50 | */
51 | private Camera mCamera;
52 | private SurfaceTexture mSurfaceTexture;
53 |
54 | //private final FBORenderTarget mRenderTarget = new FBORenderTarget();
55 | private final OESTexture mCameraTexture = new OESTexture();
56 | // private final Shader mOffscreenShader = new Shader();
57 | private PolarrRender polarrRender = new PolarrRender();
58 | private int mOutputTexture;
59 | private int mWidth, mHeight;
60 | private boolean updateTexture = false;
61 | private float[] mOrientationM = new float[16];
62 |
63 | private long[] frameList = new long[100];
64 | private long lastFrameTime;
65 | private List drawingItems;
66 |
67 | {
68 | Arrays.fill(frameList, -1);
69 | }
70 |
71 | private int frameIndex = 0;
72 |
73 | private long[] renderDuringList = new long[100];
74 |
75 | {
76 | Arrays.fill(renderDuringList, -1);
77 | }
78 |
79 | private int renderDuringIndex = 0;
80 |
81 |
82 | public CameraRenderView(Context context) {
83 | super(context);
84 | mContext = context;
85 | init();
86 | }
87 |
88 | public CameraRenderView(Context context, AttributeSet attrs) {
89 | super(context, attrs);
90 | mContext = context;
91 | init();
92 | }
93 |
94 | private void init() {
95 | setPreserveEGLContextOnPause(true);
96 | setEGLContextClientVersion(2);
97 | setRenderer(this);
98 | setRenderMode(CameraRenderView.RENDERMODE_WHEN_DIRTY);
99 | }
100 |
101 | @Override
102 | public synchronized void onFrameAvailable(SurfaceTexture surfaceTexture) {
103 | updateTexture = true;
104 | requestRender();
105 | }
106 |
107 | @Override
108 | public synchronized void onSurfaceCreated(GL10 gl, EGLConfig config) {
109 | int texType = PolarrRender.EXTERNAL_OES;
110 | if (DEBUG_DEMO_TEXTURE2D_INPUT) {
111 | texType = PolarrRender.TEXTURE_2D;
112 | }
113 |
114 | polarrRender.initRender(getResources(), 2, 2, true, texType);
115 | }
116 |
117 | @Override
118 | public synchronized void onSurfaceChanged(GL10 gl, int width, int height) {
119 | // force set the surface size
120 | // width = 1080;
121 | // height = 1440;
122 | mWidth = width;
123 | mHeight = height;
124 |
125 | mOutputTexture = genOutputTexture();
126 | // polarrRender.setOutputTexture(mOutputTexture);
127 |
128 | long startTime = System.currentTimeMillis();
129 | polarrRender.updateSize(mWidth, mHeight);
130 | Log.d("updateSize", (System.currentTimeMillis() - startTime) + "ms");
131 | Log.d("ver", PolarrRender.Version());
132 | //generate camera texture------------------------
133 | mCameraTexture.init();
134 | if (DEBUG_DEMO_TEXTURE2D_INPUT) {
135 | int[] textures = new int[1];
136 | GLES20.glGenTextures(1, textures, 0);
137 | int inputTexture = textures[0];
138 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, inputTexture);
139 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
140 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
141 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
142 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
143 |
144 | Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
145 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, inputTexture);
146 | GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, bitmap, 0);
147 | bitmap.recycle();
148 |
149 | polarrRender.setInputTexture(inputTexture);
150 | } else if (DEBUG_DEMO_OES_INPUT) {
151 | OESTexture oesTexture = new OESTexture();
152 | oesTexture.init();
153 | SurfaceTexture mSurfaceTexture = new SurfaceTexture(oesTexture.getTextureId());
154 | Surface mSurface = new Surface(mSurfaceTexture);
155 | mSurfaceTexture.setDefaultBufferSize(mWidth, mHeight);
156 | Canvas surfaceCanvas = mSurface.lockCanvas(null);
157 | Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.sample);
158 | surfaceCanvas.drawBitmap(bitmap, 0, 0, new Paint());
159 | bitmap.recycle();
160 | mSurface.unlockCanvasAndPost(surfaceCanvas);
161 | mSurfaceTexture.updateTexImage();
162 | mSurface.release();
163 | mSurfaceTexture.release();
164 | polarrRender.setInputTexture(oesTexture.getTextureId());
165 | } else {
166 | polarrRender.setInputTexture(mCameraTexture.getTextureId());
167 | }
168 |
169 | //set up surfacetexture------------------
170 | SurfaceTexture oldSurfaceTexture = mSurfaceTexture;
171 | mSurfaceTexture = new SurfaceTexture(mCameraTexture.getTextureId());
172 | mSurfaceTexture.setOnFrameAvailableListener(this);
173 | if (oldSurfaceTexture != null) {
174 | oldSurfaceTexture.release();
175 | }
176 |
177 | //set camera para-----------------------------------
178 | int camera_width = 0;
179 | int camera_height = 0;
180 |
181 | if (mCamera != null) {
182 | mCamera.stopPreview();
183 | mCamera.release();
184 | mCamera = null;
185 | }
186 |
187 | mCamera = Camera.open();
188 | try {
189 | mCamera.setPreviewTexture(mSurfaceTexture);
190 | } catch (IOException ioe) {
191 | ioe.printStackTrace();
192 | }
193 |
194 | Camera.Parameters param = mCamera.getParameters();
195 | List psize = param.getSupportedPreviewSizes();
196 | if (psize.size() > 0) {
197 | int i;
198 | for (i = 0; i < psize.size(); i++) {
199 | if (psize.get(i).width < width || psize.get(i).height < height)
200 | break;
201 | }
202 | if (i > 0)
203 | i--;
204 | param.setPreviewSize(psize.get(i).width, psize.get(i).height);
205 |
206 | camera_width = psize.get(i).width;
207 | camera_height = psize.get(i).height;
208 |
209 | }
210 |
211 | //get the camera orientation and display dimension------------
212 | if (mContext.getResources().getConfiguration().orientation ==
213 | Configuration.ORIENTATION_PORTRAIT) {
214 | Matrix.setRotateM(mOrientationM, 0, 90.0f, 0f, 0f, 1f);
215 | } else {
216 | Matrix.setRotateM(mOrientationM, 0, 0.0f, 0f, 0f, 1f);
217 | }
218 | Matrix.scaleM(mOrientationM, 0, 1, -1, 1);
219 | param.setPictureFormat(PixelFormat.JPEG);
220 | param.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
221 |
222 | //start camera-----------------------------------------
223 | mCamera.setParameters(param);
224 | mCamera.startPreview();
225 |
226 |
227 | //start render---------------------
228 | requestRender();
229 | }
230 |
231 | @Override
232 | public synchronized void onDrawFrame(GL10 gl) {
233 | if (lastFrameTime != 0) {
234 | frameList[frameIndex++] = (System.currentTimeMillis() - lastFrameTime);
235 | frameIndex %= frameList.length;
236 | }
237 | lastFrameTime = System.currentTimeMillis();
238 |
239 | GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
240 | GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
241 |
242 | if (mSurfaceTexture == null) {
243 | return;
244 | }
245 | //render the texture to FBO if new frame is available
246 | if (updateTexture) {
247 | mSurfaceTexture.updateTexImage();
248 | updateTexture = false;
249 | }
250 |
251 | if (drawingItems != null) {
252 | long startTime = System.currentTimeMillis();
253 |
254 | polarrRender.drawFiltersFrame(drawingItems, mOutputTexture);
255 |
256 | GLES20.glViewport(0, 0, mWidth, mHeight);
257 |
258 | Basic filter = Basic.getInstance(getResources());
259 | filter.setInputTextureId(mOutputTexture);
260 |
261 | if (DEBUG_DEMO_TEXTURE2D_INPUT) {
262 | Matrix.scaleM(filter.getMatrix(), 0, 1, -1, 1);
263 | } else if (DEBUG_DEMO_OES_INPUT) {
264 | Matrix.scaleM(filter.getMatrix(), 0, 1, 1, 1);
265 | } else {
266 | // update the matrix for camera orientation
267 | Matrix.setIdentityM(filter.getMatrix(), 0);
268 | Matrix.multiplyMM(filter.getMatrix(), 0, filter.getMatrix(), 0, mOrientationM, 0);
269 | }
270 | filter.draw();
271 | renderDuringList[renderDuringIndex++] = (System.currentTimeMillis() - startTime);
272 | renderDuringIndex %= renderDuringList.length;
273 | } else {
274 | long startTime = System.currentTimeMillis();
275 | polarrRender.updateInputTexture();
276 | polarrRender.drawFrame();
277 | GLES20.glViewport(0, 0, mWidth, mHeight);
278 | // demo draw screen
279 | Basic filter = Basic.getInstance(getResources());
280 | filter.setInputTextureId(polarrRender.getOutputId());
281 | filter.setNeedClear(false);
282 |
283 | if (DEBUG_DEMO_TEXTURE2D_INPUT) {
284 | Matrix.scaleM(filter.getMatrix(), 0, 1, -1, 1);
285 | } else if (DEBUG_DEMO_OES_INPUT) {
286 | Matrix.scaleM(filter.getMatrix(), 0, 1, 1, 1);
287 | } else {
288 | // update the matrix for camera orientation
289 | Matrix.setIdentityM(filter.getMatrix(), 0);
290 | Matrix.multiplyMM(filter.getMatrix(), 0, filter.getMatrix(), 0, mOrientationM, 0);
291 | }
292 |
293 | filter.draw();
294 |
295 | renderDuringList[renderDuringIndex++] = (System.currentTimeMillis() - startTime);
296 | renderDuringIndex %= renderDuringList.length;
297 | }
298 |
299 | if (frameIndex % 60 == 0) {
300 | printDuring();
301 | }
302 | }
303 |
304 | private void printDuring() {
305 | int total = 0;
306 | for (long during : frameList) {
307 | if (during == -1) {
308 | return;
309 | }
310 | total += during;
311 | }
312 | total /= frameList.length;
313 | Log.d("Frame_TIME", String.format(Locale.ENGLISH, "%d ms. %.2f fps", total, 1000f / total));
314 |
315 | total = 0;
316 | for (long during : renderDuringList) {
317 | if (during == -1) {
318 | return;
319 | }
320 | total += during;
321 | }
322 | total /= renderDuringList.length;
323 | Log.d("RENDER_TIME", total + "ms");
324 | }
325 |
326 | public void onDestroy() {
327 | updateTexture = false;
328 | if (mSurfaceTexture != null) {
329 | mSurfaceTexture.release();
330 | mSurfaceTexture = null;
331 | }
332 | if (mCamera != null) {
333 | mCamera.stopPreview();
334 | mCamera.setPreviewCallback(null);
335 | mCamera.release();
336 | }
337 |
338 | mCamera = null;
339 | }
340 |
341 | public void updateFilter(final String filterId) {
342 | queueEvent(new Runnable() {
343 | @Override
344 | public void run() {
345 | drawingItems = null;
346 | polarrRender.fastUpdateFilter(filterId);
347 |
348 | Arrays.fill(frameList, -1);
349 | }
350 | });
351 | }
352 |
353 | public void setTestFilters(final List filterIds) {
354 | // sync render thread
355 | queueEvent(new Runnable() {
356 | @Override
357 | public void run() {
358 | drawingItems = new ArrayList<>();
359 | int index = 0;
360 | int padding = 20;
361 | int width = 300;
362 | int height = 500;
363 | int colums = 3;
364 | for (String filterId : filterIds) {
365 | int raw = index / colums;
366 | int col = index % colums;
367 |
368 | DrawingItem drawingItem = new DrawingItem();
369 | drawingItem.filterId = filterId;
370 | drawingItem.rect = new Rect(col * (width + padding), raw * (height + padding), col * (width + padding) + width, raw * (height + padding) + height);
371 |
372 | drawingItems.add(drawingItem);
373 |
374 | index++;
375 | }
376 |
377 | Arrays.fill(frameList, -1);
378 |
379 | polarrRender.clearTexture(mOutputTexture, mWidth, mHeight);
380 | }
381 | });
382 | }
383 |
384 | public void takePhoto(final OnCaptureCallback onCaptureCallback) {
385 | queueEvent(new Runnable() {
386 | @Override
387 | public void run() {
388 | Bitmap bitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
389 | bitmap.copyPixelsFromBuffer(readTexture(polarrRender.getOutputId(), mWidth, mHeight));
390 |
391 | onCaptureCallback.onPhoto(bitmap);
392 | }
393 | });
394 | }
395 |
396 | private void resize(int width, int height) {
397 | polarrRender.updateSize(width, height);
398 |
399 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, polarrRender.getOutputId());
400 | GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGB, width, height,
401 | 0, GLES20.GL_RGB, GLES20.GL_UNSIGNED_BYTE, null);
402 |
403 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
404 | }
405 |
406 | private int genOutputTexture() {
407 | int[] textures = new int[1];
408 | GLES20.glGenTextures(1, textures, 0);
409 |
410 | int texture = textures[0];
411 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture);
412 | GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGB, mWidth, mHeight,
413 | 0, GLES20.GL_RGB, GLES20.GL_UNSIGNED_BYTE, null);
414 |
415 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
416 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
417 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
418 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
419 |
420 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
421 |
422 | return texture;
423 | }
424 |
425 | private static ByteBuffer readTexture(int texId, int width, int height) {
426 | int channels = 4;
427 | ByteBuffer ib = ByteBuffer.allocate(width * height * channels);
428 | int[] fFrame = new int[1];
429 | GLES20.glGenFramebuffers(1, fFrame, 0);
430 | bindFrameTexture(fFrame[0], texId);
431 | GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, ib);
432 | unBindFrameBuffer();
433 | GLES20.glDeleteFramebuffers(1, fFrame, 0);
434 | return ib;
435 | }
436 |
437 | private static void bindFrameTexture(int frameBufferId, int textureId) {
438 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frameBufferId);
439 | GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0,
440 | GLES20.GL_TEXTURE_2D, textureId, 0);
441 | }
442 |
443 | private static void unBindFrameBuffer() {
444 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
445 | }
446 |
447 | public interface OnCaptureCallback {
448 | void onPhoto(Bitmap bitmap);
449 | }
450 | }
--------------------------------------------------------------------------------