diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 000000000..9ddc91238 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,28 @@ +# Future Task + +## What is the motivation? + +## What kind of solution can be considered? + +## What do you want to discuss? + +*Please add relevant labels* + +----- + +# Bug Reporting + +## Steps to Reproduce + +## Actual Results (include screenshots) + +## Expected Results (include screenshots) + +## URL + +## OS details + +- Device: +- OS: + +*Please add relevant labels* diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..9a972544c --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,6 @@ +## What does this change? + +## What is the value of this and can you measure success? + +## Screenshots + diff --git a/.gitignore b/.gitignore index f99652d1c..141face5e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,23 +1,65 @@ -.DS_Store -Thumbs.db +# Mac OS +.DS_store -# gradle files -.gradle +# Built application files +*.apk +*.ap_ -# Intellij project files -.idea -*.iml +# Files for the ART/Dalvik VM +*.dex + +# Java class files +*.class -# generated files +# Generated files bin/ gen/ -obj/ -apk/ -target/ -build/ +out/ +# Gradle files +.gradle/ +build/ # Local configuration file (sdk path, etc) local.properties # Proguard folder generated by Eclipse proguard/ + +# Log Files +*.log + +# Android Studio Navigation editor temp files +.navigation/ + +# Android Studio captures folder +captures/ + +# IntelliJ +*.iml +.idea/ +projectFilesBackup/ + +# Keystore files +# Uncomment the following line if you do not want to check your keystore files in. +#*.jks + +# External native build folder generated in Android Studio 2.2 and later +.externalNativeBuild + +# Google Services (e.g. APIs or Firebase) +google-services.json + +# Freeline +fastlane/README.md +fastlane/report.xml + +# fastlane +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots +fastlane/test_output +fastlane/readme.md + +# NDK +.externalNativeBuild +.cxx diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c89ae59e..9cb72e3c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,65 @@ Change Log ========== -Version 1.4.1 *(2016-03-15)* +Version 2.1.0 *(2020-09-21)* +---------------------------- + +* Update + * Kotlin to 1.3.72 + * The targetSdkVersion from 28 to 30 + * The compileSdkVersion from 28 to 30 + +Version 2.0.4 *(2019-08-13)* +---------------------------- + +* Update + * Kotlin to 1.3.41 + * Android Gradle tools to 3.6.0-alpha05 + * Gradle wrapper to 5.5 + +* Add + 64bit build settings for clearly + Can get size of rescaled image [#443](https://github.com/cats-oss/android-gpuimage/pull/443) + +* Bug fix + GPUImageZoomBlurFilter incorrect args [#454](https://github.com/cats-oss/android-gpuimage/pull/454) + +Version 2.0.3 *(2018-11-09)* +---------------------------- + +* Add GPUImageVibranceFilter (by @itome) + +Version 2.0.2 *(2018-11-01)* ---------------------------- -Using Bintray's JCenter. +* Add GPUImageSolarizeFilter (by @kettsun0123) +* Change attr/names + `show_loading` to `gpuimage_show_loading` + `surface_type` to `gpuimage_surface_type` + +* Fix a bug about filter init [#420](https://github.com/cats-oss/android-gpuimage/pull/420) + +Version 2.0.1 *(2018-10-24)* +---------------------------- + +* Add GPUImageLuminanceFilter (by @takasfz) +* Add GPUImageLuminanceThresholdFilter (by @takasfz) + +Version 2.0.0 *(2018-10-23)* +---------------------------- + +* Change the minSdkVersion 9 to 14 +* Change the targetSdkVersion 23 to 28 +* Update project settings +* Support TextureView via GLTexureView +* Support Camera2 API +* Fix some bugs + + +Version 1.4.1 *(2016-03-15)* +---------------------------- + Using Bintray's JCenter. Version 1.4.0 *(2016-02-28)* ---------------------------- @@ -18,10 +72,10 @@ Version 1.4.0 *(2016-02-28)* Version 1.3.0 *(2015-09-04)* ---------------------------- - * added GPUImageBilateralFilter (by @wysaid) - * added flip options to `GPUImage#setRotation` +* added GPUImageBilateralFilter (by @wysaid) +* added flip options to `GPUImage#setRotation` Version 1.2.3-SNAPSHOT *(2014-12-15)* ---------------------------- - * added GPUImageLevelsFilter (by @vashisthg) +* added GPUImageLevelsFilter (by @vashisthg) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..c4e67647b --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,27 @@ +# How to Contribute + +We'd love to accept your patches and contributions to this project. There are +just a few small guidelines you need to follow. + +## Contributor License Agreement + +Contributions to this project must be accompanied by a Contributor License +Agreement. You (or your employer) retain the copyright to your contribution, +this simply gives us permission to use and redistribute your contributions as +part of the project. Head over to to see +your current agreements on file or to sign a new one. + +You generally only need to submit a CLA once, so if you've already submitted one +(even if it was for a different project), you probably don't need to do it +again. + +## Code reviews + +All submissions, including submissions by project members, require review. We +use GitHub pull requests for this purpose. Consult +[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more +information on using pull requests. + +## Community Guidelines + +This project follows [Google's Open Source Community Guidelines](https://opensource.google.com/conduct/). \ No newline at end of file diff --git a/README.md b/README.md index 0ac613271..dffd063aa 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,10 @@ # GPUImage for Android [![License](https://img.shields.io/badge/license-Apache%202-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0) -[![Download](https://api.bintray.com/packages/cyberagent/maven/gpuimage-library/images/download.svg) ](https://bintray.com/cyberagent/maven/gpuimage-library/_latestVersion) +[![Download](https://api.bintray.com/packages/cats-oss/maven/gpuimage/images/download.svg) ](https://bintray.com/cats-oss/maven/gpuimage/_latestVersion) +[![Maven Central](https://maven-badges.herokuapp.com/maven-central/jp.co.cyberagent.android/gpuimage/badge.svg)](https://search.maven.org/artifact/jp.co.cyberagent.android/gpuimage) +[![Build Status](https://app.bitrise.io/app/d8d8090a71066e7c/status.svg?token=sJNbvX8CkecWcUA5Z898lQ&branch=master)](https://app.bitrise.io/app/d8d8090a71066e7c) -Idea from: [iOS GPUImage framework](https://github.com/BradLarson/GPUImage) +Idea from: [iOS GPUImage framework](https://github.com/BradLarson/GPUImage2) Goal is to have something as similar to GPUImage as possible. Vertex and fragment shaders are exactly the same. That way it makes it easier to port filters from GPUImage iOS to Android. @@ -15,17 +17,18 @@ Goal is to have something as similar to GPUImage as possible. Vertex and fragmen ```groovy repositories { - jcenter() + mavenCentral() } dependencies { - compile 'jp.co.cyberagent.android.gpuimage:gpuimage-library:1.4.1' + implementation 'jp.co.cyberagent.android:gpuimage:2.x.x' } ``` ### Sample Code -With preview: +#### With preview: +Java: ```java @Override public void onCreate(final Bundle savedInstanceState) { @@ -33,26 +36,222 @@ public void onCreate(final Bundle savedInstanceState) { setContentView(R.layout.activity); Uri imageUri = ...; - mGPUImage = new GPUImage(this); - mGPUImage.setGLSurfaceView((GLSurfaceView) findViewById(R.id.surfaceView)); - mGPUImage.setImage(imageUri); // this loads image on the current thread, should be run in a thread - mGPUImage.setFilter(new GPUImageSepiaFilter()); + gpuImage = new GPUImage(this); + gpuImage.setGLSurfaceView((GLSurfaceView) findViewById(R.id.surfaceView)); + gpuImage.setImage(imageUri); // this loads image on the current thread, should be run in a thread + gpuImage.setFilter(new GPUImageSepiaFilter()); // Later when image should be saved saved: - mGPUImage.saveToPictures("GPUImage", "ImageWithFilter.jpg", null); + gpuImage.saveToPictures("GPUImage", "ImageWithFilter.jpg", null); } ``` -Without preview: +Kotlin: +```kotlin +public override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_gallery) + val imageUri: Uri = ... + gpuImage = GPUImage(this) + gpuImage.setGLSurfaceView(findViewById(R.id.surfaceView)) + gpuImage.setImage(imageUri) // this loads image on the current thread, should be run in a thread + gpuImage.setFilter(GPUImageSepiaFilter()) + + // Later when image should be saved saved: + gpuImage.saveToPictures("GPUImage", "ImageWithFilter.jpg", null) +} +``` + +#### Using GPUImageView +```xml + +``` + +Java: +```java +@Override +public void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity); + + Uri imageUri = ...; + gpuImageView = findViewById(R.id.gpuimageview); + gpuImageView.setImage(imageUri); // this loads image on the current thread, should be run in a thread + gpuImageView.setFilter(new GPUImageSepiaFilter()); + + // Later when image should be saved saved: + gpuImageView.saveToPictures("GPUImage", "ImageWithFilter.jpg", null); +} +``` + +Kotlin: +```kotlin +public override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_gallery) + + val imageUri: Uri = ... + gpuImageView = findViewById(R.id.gpuimageview) + gpuImageView.setImage(imageUri) // this loads image on the current thread, should be run in a thread + gpuImageView.setFilter(GPUImageSepiaFilter()) + + // Later when image should be saved saved: + gpuImageView.saveToPictures("GPUImage", "ImageWithFilter.jpg", null) +} +``` + +#### Without preview: + +Java: ```java -Uri imageUri = ...; -mGPUImage = new GPUImage(context); -mGPUImage.setFilter(new GPUImageSobelEdgeDetection()); -mGPUImage.setImage(imageUri); -mGPUImage.saveToPictures("GPUImage", "ImageWithFilter.jpg", null); +public void onCreate(final Bundle savedInstanceState) { + public void onCreate(final Bundle savedInstanceState) { + Uri imageUri = ...; + gpuImage = new GPUImage(context); + gpuImage.setFilter(new GPUImageSobelEdgeDetection()); + gpuImage.setImage(imageUri); + gpuImage.saveToPictures("GPUImage", "ImageWithFilter.jpg", null); +} +``` + +Kotlin: +```kotlin +public override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_gallery) + val imageUri: Uri = ... + gpuImage = GPUImage(this) + gpuImage.setFilter(GPUImageSepiaFilter()) + gpuImage.setImage(imageUri) + gpuImage.saveToPictures("GPUImage", "ImageWithFilter.jpg", null) +} ``` +### Support status of [GPUImage for iOS](https://github.com/BradLarson/GPUImage2) shaders +- [x] Saturation +- [x] Contrast +- [x] Brightness +- [x] Levels +- [x] Exposure +- [x] RGB +- [x] RGB Diation +- [x] Hue +- [x] White Balance +- [x] Monochrome +- [x] False Color +- [x] Sharpen +- [ ] Unsharp Mask +- [x] Transform Operation +- [ ] Crop +- [x] Gamma +- [x] Highlights and Shadows +- [x] Haze +- [x] Sepia Tone +- [ ] Amatorka +- [ ] Miss Etikate +- [ ] Soft Elegance +- [x] Color Inversion +- [x] Solarize +- [x] Vibrance +- [ ] Highlight and Shadow Tint +- [x] Luminance +- [x] Luminance Threshold +- [ ] Average Color +- [ ] Average Luminance +- [ ] Average Luminance Threshold +- [ ] Adaptive Threshold +- [ ] Polar Pixellate +- [x] Pixellate +- [ ] Polka Dot +- [x] Halftone +- [x] Crosshatch +- [x] Sobel Edge Detection +- [ ] Prewitt Edge Detection +- [ ] Canny Edge Detection +- [x] Threshold Sobel EdgeDetection +- [ ] Harris Corner Detector +- [ ] Noble Corner Detector +- [ ] Shi Tomasi Feature Detector +- [ ] Colour FAST Feature Detector +- [ ] Low Pass Filter +- [ ] High Pass Filter +- [x] Sketch Filter +- [ ] Threshold Sketch Filter +- [x] Toon Filter +- [x] SmoothToon Filter +- [ ] Tilt Shift +- [x] CGA Colorspace Filter +- [x] Posterize +- [x] Convolution 3x3 +- [x] Emboss Filter +- [x] Laplacian +- [x] Chroma Keying +- [x] Kuwahara Filter +- [ ] Kuwahara Radius3 Filter +- [x] Vignette +- [x] Gaussian Blur +- [x] Box Blur +- [x] Bilateral Blur +- [ ] Motion Blur +- [x] Zoom Blur +- [ ] iOS Blur +- [ ] Median Filter +- [x] Swirl Distortion +- [x] Bulge Distortion +- [ ] Pinch Distortion +- [x] Sphere Refraction +- [x] Glass Sphere Refraction +- [ ] Stretch Distortion +- [x] Dilation +- [ ] Erosion +- [ ] Opening Filter +- [ ] Closing Filter +- [ ] Local Binary Pattern +- [ ] Color Local Binary Pattern +- [x] Dissolve Blend +- [x] Chroma Key Blend +- [x] Add Blend +- [x] Divide Blend +- [x] Multiply Blend +- [x] Overlay Blend +- [x] Lighten Blend +- [x] Darken Blend +- [x] Color Burn Blend +- [x] Color Dodge Blend +- [x] Linear Burn Blend +- [x] Screen Blend +- [x] Difference Blend +- [x] Subtract Blend +- [x] Exclusion Blend +- [x] HardLight Blend +- [x] SoftLight Blend +- [x] Color Blend +- [x] Hue Blend +- [x] Saturation Blend +- [x] Luminosity Blend +- [x] Normal Blend +- [x] Source Over Blend +- [x] Alpha Blend +- [x] Non Maximum Suppression +- [ ] Thresholded Non Maximum Suppression +- [ ] Directional Non Maximum Suppression +- [x] Opacity +- [x] Weak Pixel Inclusion Filter +- [x] Color Matrix +- [x] Directional Sobel Edge Detection +- [x] Lookup +- [x] Tone Curve (*.acv files) + +## Others +- [x] Texture 3x3 +- [x] Gray Scale + ### Gradle Make sure that you run the clean target when using maven. @@ -61,7 +260,7 @@ gradle clean assemble ``` ## License - Copyright 2012 CyberAgent, Inc. + Copyright 2018 CyberAgent, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/build.gradle b/build.gradle index 8a29e6b0d..72026fdd6 100644 --- a/build.gradle +++ b/build.gradle @@ -1,21 +1,29 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { + ext.kotlin_version = '1.3.72' repositories { + google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.0.0-beta6' - classpath 'com.novoda:bintray-release:0.3.4' + classpath 'com.android.tools.build:gradle:4.2.0-beta04' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + +// TODO: Close JCenter on May 1st https://jfrog.com/blog/into-the-sunset-bintray-jcenter-gocenter-and-chartcenter/ +// classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.5' +// classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1' } } allprojects { repositories { + google() + mavenCentral() jcenter() - maven { url("https://oss.sonatype.org/content/repositories/snapshots/") } - } - tasks.withType(JavaCompile) { - options.encoding = 'UTF-8' } } + +task clean(type: Delete) { + delete rootProject.buildDir +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 40c44d7f8..bd6a24475 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,22 +1,26 @@ -VERSION_NAME=1.4.1 -GROUP=jp.co.cyberagent.android.gpuimage -ARTIFACT_ID=gpuimage-library +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=1024m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +org.gradle.parallel=true +org.gradle.daemon=true +org.gradle.configureondemand=true +org.gradle.caching=true +android.enableBuildCache=true -COMPILE_SDK_VERSION=23 -BUILD_TOOLS_VERSION=23.0.2 -TARGET_SDK_VERSION=23 -MIN_SDK_VERSION=8 +VERSION_NAME=2.1.0 +VERSION_CODE=14 -POM_DESCRIPTION=Image filters for Android with OpenGL (based on GPUImage for iOS) -POM_URL=https://github.com/cyberagent/android-gpuimage -POM_SCM_URL=scm:git@github.com:CyberAgent/android-gpuimage.git -POM_SCM_CONNECTION=scm:git@github.com:CyberAgent/android-gpuimage.git -POM_SCM_DEV_CONNECTION=scm:git@github.com:CyberAgent/android-gpuimage.git -POM_LICENCE_NAME=The Apache Software License, Version 2.0 -POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt -POM_LICENCE_DIST=repo -POM_DEVELOPER_ID=cyberagent -POM_DEVELOPER_NAME=CyberAgent, Inc. -ISSUE_URL=https://github.com/CyberAgent/android-gpuimage/issues +COMPILE_SDK_VERSION=30 +TARGET_SDK_VERSION=30 +MIN_SDK_VERSION=14 -android.useDeprecatedNdk=true +android.useAndroidX=true +android.enableJetifier=true diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 8c0fb64a8..e708b1c02 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 6c0732abc..a7a55a149 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Sat Dec 06 18:27:05 JST 2014 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https://services.gradle.org/distributions/gradle-6.7.1-bin.zip zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.11-all.zip +zipStorePath=wrapper/dists \ No newline at end of file diff --git a/gradlew b/gradlew index 91a7e269e..4f906e0c8 100755 --- a/gradlew +++ b/gradlew @@ -1,4 +1,20 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# 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 +# +# https://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. +# ############################################################################## ## @@ -6,20 +22,38 @@ ## ############################################################################## -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" -warn ( ) { +warn () { echo "$*" } -die ( ) { +die () { echo echo "$*" echo @@ -30,6 +64,7 @@ die ( ) { cygwin=false msys=false darwin=false +nonstop=false case "`uname`" in CYGWIN* ) cygwin=true @@ -40,33 +75,14 @@ case "`uname`" in MINGW* ) msys=true ;; + NONSTOP* ) + nonstop=true + ;; esac -# For Cygwin, ensure paths are in UNIX format before anything is touched. -if $cygwin ; then - [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` -fi - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >&- -APP_HOME="`pwd -P`" -cd "$SAVED" >&- - CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then @@ -90,7 +106,7 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then @@ -110,11 +126,13 @@ if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + # We build the pattern for arguments to be converted via cygpath ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` SEP="" @@ -138,27 +156,30 @@ if $cygwin ; then else eval `echo args$i`="\"$arg\"" fi - i=$((i+1)) + i=`expr $i + 1` done case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " } -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index aec99730b..ac1b06f93 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,3 +1,19 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @@ -8,20 +24,23 @@ @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -35,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -45,34 +64,14 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windowz variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell diff --git a/library/AndroidManifest.xml b/library/AndroidManifest.xml deleted file mode 100644 index ee0e77580..000000000 --- a/library/AndroidManifest.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - \ No newline at end of file diff --git a/library/build.gradle b/library/build.gradle index 4e0ded68c..c13645463 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -1,72 +1,56 @@ apply plugin: 'com.android.library' -apply plugin: 'com.novoda.bintray-release' android { compileSdkVersion COMPILE_SDK_VERSION as int - buildToolsVersion BUILD_TOOLS_VERSION defaultConfig { minSdkVersion MIN_SDK_VERSION as int targetSdkVersion TARGET_SDK_VERSION as int - versionCode "git rev-list origin/master --count".execute().text.toInteger() - versionName VERSION_NAME - - consumerProguardFiles 'proguard-rules.txt' - - ndk { - moduleName "gpuimage-library" - stl "gnustl_shared" - abiFilters "all" - ldLibs "log" + versionCode = VERSION_CODE as int + versionName = VERSION_NAME + ndk.abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64' + externalNativeBuild { + cmake { cppFlags "" } } } - - sourceSets { - main { - manifest.srcFile 'AndroidManifest.xml' - java.srcDirs = ['src'] - resources.srcDirs = ['src'] - aidl.srcDirs = ['src'] - renderscript.srcDirs = ['src'] - res.srcDirs = ['res'] - assets.srcDirs = ['assets'] - jni.srcDirs = ['jni'] - } - - instrumentTest.setRoot('tests') + externalNativeBuild { + cmake { path "src/main/cpp/CMakeLists.txt" } } - lintOptions { - abortOnError false + buildTypes { + debug { + debuggable true + } + release { + debuggable false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } } } -task androidJavadocs(type: Javadoc) { - source = android.sourceSets.main.java.srcDirs - classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) +ext { + bintrayRepo = 'maven' + bintrayName = 'gpuimage' + bintrayUserOrg = 'cats-oss' + publishedGroupId = 'jp.co.cyberagent.android' + libraryName = 'gpuimage' + artifact = 'gpuimage' + libraryDescription = 'Image filters for Android with OpenGL (based on GPUImage for iOS)' + siteUrl = 'https://github.com/cats-oss/android-gpuimage' + gitUrl = 'https://github.com/cats-oss/android-gpuimage.git' + issueUrl = 'https://github.com/cats-oss/android-gpuimage/issues' + libraryVersion = VERSION_NAME + developerId = 'cats' + developerName = 'CATS' + developerEmail = 'dadadada.chop@gmail.com' + licenseName = 'The Apache Software License, Version 2.0' + licenseUrl = 'http://www.apache.org/licenses/LICENSE-2.0.txt' + allLicenses = ["Apache-2.0"] } -task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) { - classifier = 'javadoc' - from androidJavadocs.destinationDir -} - -task androidSourcesJar(type: Jar) { - classifier = 'sources' - from android.sourceSets.main.java.srcDirs -} +// TODO: Close JCenter on May 1st https://jfrog.com/blog/into-the-sunset-bintray-jcenter-gocenter-and-chartcenter/ +// apply from: 'https://gist.githubusercontent.com/wasabeef/cf14805bee509baf7461974582f17d26/raw/bintray-v1.gradle' +// apply from: 'https://gist.githubusercontent.com/wasabeef/cf14805bee509baf7461974582f17d26/raw/install-v1.gradle' -artifacts { - archives androidSourcesJar - archives androidJavadocsJar -} - -publish { - userOrg = POM_DEVELOPER_ID - groupId = GROUP - artifactId = ARTIFACT_ID - publishVersion = VERSION_NAME - desc = POM_DESCRIPTION - website = POM_URL -} +apply from: 'https://gist.githubusercontent.com/wasabeef/2f2ae8d97b429e7d967128125dc47854/raw/maven-central-v1.gradle' \ No newline at end of file diff --git a/library/jni/yuv-decoder.c b/library/jni/yuv-decoder.c deleted file mode 100644 index fed6281e8..000000000 --- a/library/jni/yuv-decoder.c +++ /dev/null @@ -1,115 +0,0 @@ -#include -#include - - -JNIEXPORT void JNICALL Java_jp_co_cyberagent_android_gpuimage_GPUImageNativeLibrary_YUVtoRBGA(JNIEnv * env, jobject obj, jbyteArray yuv420sp, jint width, jint height, jintArray rgbOut) -{ - int sz; - int i; - int j; - int Y; - int Cr = 0; - int Cb = 0; - int pixPtr = 0; - int jDiv2 = 0; - int R = 0; - int G = 0; - int B = 0; - int cOff; - int w = width; - int h = height; - sz = w * h; - - jint *rgbData = (jint*) ((*env)->GetPrimitiveArrayCritical(env, rgbOut, 0)); - jbyte* yuv = (jbyte*) (*env)->GetPrimitiveArrayCritical(env, yuv420sp, 0); - - for(j = 0; j < h; j++) { - pixPtr = j * w; - jDiv2 = j >> 1; - for(i = 0; i < w; i++) { - Y = yuv[pixPtr]; - if(Y < 0) Y += 255; - if((i & 0x1) != 1) { - cOff = sz + jDiv2 * w + (i >> 1) * 2; - Cb = yuv[cOff]; - if(Cb < 0) Cb += 127; else Cb -= 128; - Cr = yuv[cOff + 1]; - if(Cr < 0) Cr += 127; else Cr -= 128; - } - - //ITU-R BT.601 conversion - // - //R = 1.164*(Y-16) + 2.018*(Cr-128); - //G = 1.164*(Y-16) - 0.813*(Cb-128) - 0.391*(Cr-128); - //B = 1.164*(Y-16) + 1.596*(Cb-128); - // - Y = Y + (Y >> 3) + (Y >> 5) + (Y >> 7); - R = Y + (Cr << 1) + (Cr >> 6); - if(R < 0) R = 0; else if(R > 255) R = 255; - G = Y - Cb + (Cb >> 3) + (Cb >> 4) - (Cr >> 1) + (Cr >> 3); - if(G < 0) G = 0; else if(G > 255) G = 255; - B = Y + Cb + (Cb >> 1) + (Cb >> 4) + (Cb >> 5); - if(B < 0) B = 0; else if(B > 255) B = 255; - rgbData[pixPtr++] = 0xff000000 + (R << 16) + (G << 8) + B; - } - } - - (*env)->ReleasePrimitiveArrayCritical(env, rgbOut, rgbData, 0); - (*env)->ReleasePrimitiveArrayCritical(env, yuv420sp, yuv, 0); -} - -JNIEXPORT void JNICALL Java_jp_co_cyberagent_android_gpuimage_GPUImageNativeLibrary_YUVtoARBG(JNIEnv * env, jobject obj, jbyteArray yuv420sp, jint width, jint height, jintArray rgbOut) -{ - int sz; - int i; - int j; - int Y; - int Cr = 0; - int Cb = 0; - int pixPtr = 0; - int jDiv2 = 0; - int R = 0; - int G = 0; - int B = 0; - int cOff; - int w = width; - int h = height; - sz = w * h; - - jint *rgbData = (jint*) ((*env)->GetPrimitiveArrayCritical(env, rgbOut, 0)); - jbyte* yuv = (jbyte*) (*env)->GetPrimitiveArrayCritical(env, yuv420sp, 0); - - for(j = 0; j < h; j++) { - pixPtr = j * w; - jDiv2 = j >> 1; - for(i = 0; i < w; i++) { - Y = yuv[pixPtr]; - if(Y < 0) Y += 255; - if((i & 0x1) != 1) { - cOff = sz + jDiv2 * w + (i >> 1) * 2; - Cb = yuv[cOff]; - if(Cb < 0) Cb += 127; else Cb -= 128; - Cr = yuv[cOff + 1]; - if(Cr < 0) Cr += 127; else Cr -= 128; - } - - //ITU-R BT.601 conversion - // - //R = 1.164*(Y-16) + 2.018*(Cr-128); - //G = 1.164*(Y-16) - 0.813*(Cb-128) - 0.391*(Cr-128); - //B = 1.164*(Y-16) + 1.596*(Cb-128); - // - Y = Y + (Y >> 3) + (Y >> 5) + (Y >> 7); - R = Y + (Cr << 1) + (Cr >> 6); - if(R < 0) R = 0; else if(R > 255) R = 255; - G = Y - Cb + (Cb >> 3) + (Cb >> 4) - (Cr >> 1) + (Cr >> 3); - if(G < 0) G = 0; else if(G > 255) G = 255; - B = Y + Cb + (Cb >> 1) + (Cb >> 4) + (Cb >> 5); - if(B < 0) B = 0; else if(B > 255) B = 255; - rgbData[pixPtr++] = 0xff000000 + (B << 16) + (G << 8) + R; - } - } - - (*env)->ReleasePrimitiveArrayCritical(env, rgbOut, rgbData, 0); - (*env)->ReleasePrimitiveArrayCritical(env, yuv420sp, yuv, 0); -} \ No newline at end of file diff --git a/library/project.properties b/library/project.properties deleted file mode 100644 index 93c8c3c08..000000000 --- a/library/project.properties +++ /dev/null @@ -1,15 +0,0 @@ -# This file is automatically generated by Android Tools. -# Do not modify this file -- YOUR CHANGES WILL BE ERASED! -# -# This file must be checked in Version Control Systems. -# -# To customize properties used by the Ant build system edit -# "ant.properties", and override values to adapt the script to your -# project structure. -# -# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): -#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt - -# Project target. -target=android-21 -android.library=true diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImage3x3TextureSamplingFilter.java b/library/src/jp/co/cyberagent/android/gpuimage/GPUImage3x3TextureSamplingFilter.java deleted file mode 100644 index 2e6820a3b..000000000 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImage3x3TextureSamplingFilter.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2012 CyberAgent - * - * 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 jp.co.cyberagent.android.gpuimage; - -import android.opengl.GLES20; - -public class GPUImage3x3TextureSamplingFilter extends GPUImageFilter { - public static final String THREE_X_THREE_TEXTURE_SAMPLING_VERTEX_SHADER = "" + - "attribute vec4 position;\n" + - "attribute vec4 inputTextureCoordinate;\n" + - "\n" + - "uniform highp float texelWidth; \n" + - "uniform highp float texelHeight; \n" + - "\n" + - "varying vec2 textureCoordinate;\n" + - "varying vec2 leftTextureCoordinate;\n" + - "varying vec2 rightTextureCoordinate;\n" + - "\n" + - "varying vec2 topTextureCoordinate;\n" + - "varying vec2 topLeftTextureCoordinate;\n" + - "varying vec2 topRightTextureCoordinate;\n" + - "\n" + - "varying vec2 bottomTextureCoordinate;\n" + - "varying vec2 bottomLeftTextureCoordinate;\n" + - "varying vec2 bottomRightTextureCoordinate;\n" + - "\n" + - "void main()\n" + - "{\n" + - " gl_Position = position;\n" + - "\n" + - " vec2 widthStep = vec2(texelWidth, 0.0);\n" + - " vec2 heightStep = vec2(0.0, texelHeight);\n" + - " vec2 widthHeightStep = vec2(texelWidth, texelHeight);\n" + - " vec2 widthNegativeHeightStep = vec2(texelWidth, -texelHeight);\n" + - "\n" + - " textureCoordinate = inputTextureCoordinate.xy;\n" + - " leftTextureCoordinate = inputTextureCoordinate.xy - widthStep;\n" + - " rightTextureCoordinate = inputTextureCoordinate.xy + widthStep;\n" + - "\n" + - " topTextureCoordinate = inputTextureCoordinate.xy - heightStep;\n" + - " topLeftTextureCoordinate = inputTextureCoordinate.xy - widthHeightStep;\n" + - " topRightTextureCoordinate = inputTextureCoordinate.xy + widthNegativeHeightStep;\n" + - "\n" + - " bottomTextureCoordinate = inputTextureCoordinate.xy + heightStep;\n" + - " bottomLeftTextureCoordinate = inputTextureCoordinate.xy - widthNegativeHeightStep;\n" + - " bottomRightTextureCoordinate = inputTextureCoordinate.xy + widthHeightStep;\n" + - "}"; - - private int mUniformTexelWidthLocation; - private int mUniformTexelHeightLocation; - - private boolean mHasOverriddenImageSizeFactor = false; - private float mTexelWidth; - private float mTexelHeight; - private float mLineSize = 1.0f; - - public GPUImage3x3TextureSamplingFilter() { - this(NO_FILTER_VERTEX_SHADER); - } - - public GPUImage3x3TextureSamplingFilter(final String fragmentShader) { - super(THREE_X_THREE_TEXTURE_SAMPLING_VERTEX_SHADER, fragmentShader); - } - - @Override - public void onInit() { - super.onInit(); - mUniformTexelWidthLocation = GLES20.glGetUniformLocation(getProgram(), "texelWidth"); - mUniformTexelHeightLocation = GLES20.glGetUniformLocation(getProgram(), "texelHeight"); - if (mTexelWidth != 0) { - updateTexelValues(); - } - } - - @Override - public void onOutputSizeChanged(final int width, final int height) { - super.onOutputSizeChanged(width, height); - if (!mHasOverriddenImageSizeFactor) { - setLineSize(mLineSize); - } - } - - public void setTexelWidth(final float texelWidth) { - mHasOverriddenImageSizeFactor = true; - mTexelWidth = texelWidth; - setFloat(mUniformTexelWidthLocation, texelWidth); - } - - public void setTexelHeight(final float texelHeight) { - mHasOverriddenImageSizeFactor = true; - mTexelHeight = texelHeight; - setFloat(mUniformTexelHeightLocation, texelHeight); - } - - public void setLineSize(final float size) { - mLineSize = size; - mTexelWidth = size / getOutputWidth(); - mTexelHeight = size / getOutputHeight(); - updateTexelValues(); - } - - private void updateTexelValues() { - setFloat(mUniformTexelWidthLocation, mTexelWidth); - setFloat(mUniformTexelHeightLocation, mTexelHeight); - } -} diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageBilateralFilter.java b/library/src/jp/co/cyberagent/android/gpuimage/GPUImageBilateralFilter.java deleted file mode 100644 index 275253abc..000000000 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageBilateralFilter.java +++ /dev/null @@ -1,155 +0,0 @@ -/** - * @author wysaid - * @mail admin@wysaid.org - * -*/ - -package jp.co.cyberagent.android.gpuimage; - -import android.opengl.GLES20; - - -public class GPUImageBilateralFilter extends GPUImageFilter { - public static final String BILATERAL_VERTEX_SHADER = "" + - "attribute vec4 position;\n" + - "attribute vec4 inputTextureCoordinate;\n" + - - "const int GAUSSIAN_SAMPLES = 9;\n" + - - "uniform vec2 singleStepOffset;\n" + - - "varying vec2 textureCoordinate;\n" + - "varying vec2 blurCoordinates[GAUSSIAN_SAMPLES];\n" + - - "void main()\n" + - "{\n" + - " gl_Position = position;\n" + - " textureCoordinate = inputTextureCoordinate.xy;\n" + - - " int multiplier = 0;\n" + - " vec2 blurStep;\n" + - - " for (int i = 0; i < GAUSSIAN_SAMPLES; i++)\n" + - " {\n" + - " multiplier = (i - ((GAUSSIAN_SAMPLES - 1) / 2));\n" + - - " blurStep = float(multiplier) * singleStepOffset;\n" + - " blurCoordinates[i] = inputTextureCoordinate.xy + blurStep;\n" + - " }\n" + - "}"; - - public static final String BILATERAL_FRAGMENT_SHADER = "" + - "uniform sampler2D inputImageTexture;\n" + - - " const lowp int GAUSSIAN_SAMPLES = 9;\n" + - - " varying highp vec2 textureCoordinate;\n" + - " varying highp vec2 blurCoordinates[GAUSSIAN_SAMPLES];\n" + - - " uniform mediump float distanceNormalizationFactor;\n" + - - " void main()\n" + - " {\n" + - " lowp vec4 centralColor;\n" + - " lowp float gaussianWeightTotal;\n" + - " lowp vec4 sum;\n" + - " lowp vec4 sampleColor;\n" + - " lowp float distanceFromCentralColor;\n" + - " lowp float gaussianWeight;\n" + - " \n" + - " centralColor = texture2D(inputImageTexture, blurCoordinates[4]);\n" + - " gaussianWeightTotal = 0.18;\n" + - " sum = centralColor * 0.18;\n" + - " \n" + - " sampleColor = texture2D(inputImageTexture, blurCoordinates[0]);\n" + - " distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);\n" + - " gaussianWeight = 0.05 * (1.0 - distanceFromCentralColor);\n" + - " gaussianWeightTotal += gaussianWeight;\n" + - " sum += sampleColor * gaussianWeight;\n" + - - " sampleColor = texture2D(inputImageTexture, blurCoordinates[1]);\n" + - " distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);\n" + - " gaussianWeight = 0.09 * (1.0 - distanceFromCentralColor);\n" + - " gaussianWeightTotal += gaussianWeight;\n" + - " sum += sampleColor * gaussianWeight;\n" + - - " sampleColor = texture2D(inputImageTexture, blurCoordinates[2]);\n" + - " distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);\n" + - " gaussianWeight = 0.12 * (1.0 - distanceFromCentralColor);\n" + - " gaussianWeightTotal += gaussianWeight;\n" + - " sum += sampleColor * gaussianWeight;\n" + - - " sampleColor = texture2D(inputImageTexture, blurCoordinates[3]);\n" + - " distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);\n" + - " gaussianWeight = 0.15 * (1.0 - distanceFromCentralColor);\n" + - " gaussianWeightTotal += gaussianWeight;\n" + - " sum += sampleColor * gaussianWeight;\n" + - - " sampleColor = texture2D(inputImageTexture, blurCoordinates[5]);\n" + - " distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);\n" + - " gaussianWeight = 0.15 * (1.0 - distanceFromCentralColor);\n" + - " gaussianWeightTotal += gaussianWeight;\n" + - " sum += sampleColor * gaussianWeight;\n" + - - " sampleColor = texture2D(inputImageTexture, blurCoordinates[6]);\n" + - " distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);\n" + - " gaussianWeight = 0.12 * (1.0 - distanceFromCentralColor);\n" + - " gaussianWeightTotal += gaussianWeight;\n" + - " sum += sampleColor * gaussianWeight;\n" + - - " sampleColor = texture2D(inputImageTexture, blurCoordinates[7]);\n" + - " distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);\n" + - " gaussianWeight = 0.09 * (1.0 - distanceFromCentralColor);\n" + - " gaussianWeightTotal += gaussianWeight;\n" + - " sum += sampleColor * gaussianWeight;\n" + - - " sampleColor = texture2D(inputImageTexture, blurCoordinates[8]);\n" + - " distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);\n" + - " gaussianWeight = 0.05 * (1.0 - distanceFromCentralColor);\n" + - " gaussianWeightTotal += gaussianWeight;\n" + - " sum += sampleColor * gaussianWeight;\n" + - " gl_FragColor = sum / gaussianWeightTotal;\n" + -// " gl_FragColor.r = distanceNormalizationFactor / 20.0;" + - " }"; - - private float mDistanceNormalizationFactor; - private int mDisFactorLocation; - private int mSingleStepOffsetLocation; - - public GPUImageBilateralFilter() { - this(8.0f); - } - - public GPUImageBilateralFilter(final float distanceNormalizationFactor) { - super(BILATERAL_VERTEX_SHADER, BILATERAL_FRAGMENT_SHADER); - mDistanceNormalizationFactor = distanceNormalizationFactor; - } - - @Override - public void onInit() { - super.onInit(); - mDisFactorLocation = GLES20.glGetUniformLocation(getProgram(), "distanceNormalizationFactor"); - mSingleStepOffsetLocation = GLES20.glGetUniformLocation(getProgram(), "singleStepOffset"); - } - - @Override - public void onInitialized() { - super.onInitialized(); - setDistanceNormalizationFactor(mDistanceNormalizationFactor); - } - - public void setDistanceNormalizationFactor(final float newValue) { - mDistanceNormalizationFactor = newValue; - setFloat(mDisFactorLocation, newValue); - } - - private void setTexelSize(final float w, final float h) { - setFloatVec2(mSingleStepOffsetLocation, new float[] {1.0f / w, 1.0f / h}); - } - - @Override - public void onOutputSizeChanged(final int width, final int height) { - super.onOutputSizeChanged(width, height); - setTexelSize(width, height); - } -} diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageColorBalanceFilter.java b/library/src/jp/co/cyberagent/android/gpuimage/GPUImageColorBalanceFilter.java deleted file mode 100644 index 68c078a66..000000000 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageColorBalanceFilter.java +++ /dev/null @@ -1,197 +0,0 @@ -package jp.co.cyberagent.android.gpuimage; - -import android.opengl.GLES20; - -/** - * Created by edward_chiang on 13/10/16. - */ -public class GPUImageColorBalanceFilter extends GPUImageFilter { - - public static final String GPU_IMAGE_COLOR_BALANCE_FRAGMENT_SHADER = "" + - "varying highp vec2 textureCoordinate;\n" + - "uniform sampler2D inputImageTexture;\n" + - "uniform lowp vec3 shadowsShift;\n" + - "uniform lowp vec3 midtonesShift;\n" + - "uniform lowp vec3 highlightsShift;\n" + - "uniform int preserveLuminosity;\n" + - "lowp vec3 RGBToHSL(lowp vec3 color)\n" + - - "{\n" + - "lowp vec3 hsl; // init to 0 to avoid warnings ? (and reverse if + remove first part)\n" + - - "lowp float fmin = min(min(color.r, color.g), color.b); //Min. value of RGB\n" + - "lowp float fmax = max(max(color.r, color.g), color.b); //Max. value of RGB\n" + - "lowp float delta = fmax - fmin; //Delta RGB value\n" + - - "hsl.z = (fmax + fmin) / 2.0; // Luminance\n" + - - "if (delta == 0.0) //This is a gray, no chroma...\n" + - "{\n" + - " hsl.x = 0.0; // Hue\n" + - " hsl.y = 0.0; // Saturation\n" + - "}\n" + - "else //Chromatic data...\n" + - "{\n" + - " if (hsl.z < 0.5)\n" + - " hsl.y = delta / (fmax + fmin); // Saturation\n" + - " else\n"+ - " hsl.y = delta / (2.0 - fmax - fmin); // Saturation\n" + - "\n" + - " lowp float deltaR = (((fmax - color.r) / 6.0) + (delta / 2.0)) / delta;\n" + - " lowp float deltaG = (((fmax - color.g) / 6.0) + (delta / 2.0)) / delta;\n" + - " lowp float deltaB = (((fmax - color.b) / 6.0) + (delta / 2.0)) / delta;\n" + - "\n" + - " if (color.r == fmax )\n" + - " hsl.x = deltaB - deltaG; // Hue\n" + - " else if (color.g == fmax)\n" + - " hsl.x = (1.0 / 3.0) + deltaR - deltaB; // Hue\n" + - " else if (color.b == fmax)\n" + - " hsl.x = (2.0 / 3.0) + deltaG - deltaR; // Hue\n" + - - " if (hsl.x < 0.0)\n" + - " hsl.x += 1.0; // Hue\n" + - " else if (hsl.x > 1.0)\n" + - " hsl.x -= 1.0; // Hue\n" + - "}\n" + - "\n" + - "return hsl;\n" + - "}\n" + - - "lowp float HueToRGB(lowp float f1, lowp float f2, lowp float hue)\n" + - "{\n"+ - " if (hue < 0.0)\n"+ - " hue += 1.0;\n"+ - " else if (hue > 1.0)\n"+ - " hue -= 1.0;\n"+ - " lowp float res;\n"+ - " if ((6.0 * hue) < 1.0)\n"+ - " res = f1 + (f2 - f1) * 6.0 * hue;\n"+ - " else if ((2.0 * hue) < 1.0)\n"+ - " res = f2;\n"+ - " else if ((3.0 * hue) < 2.0)\n"+ - " res = f1 + (f2 - f1) * ((2.0 / 3.0) - hue) * 6.0;\n"+ - " else\n"+ - " res = f1;\n"+ - " return res;\n"+ - "}\n"+ - - "lowp vec3 HSLToRGB(lowp vec3 hsl)\n"+ - "{\n" + - " lowp vec3 rgb;\n" + - - " if (hsl.y == 0.0)\n" + - " rgb = vec3(hsl.z); // Luminance\n" + - " else\n" + - " {\n" + - " lowp float f2;\n" + - - " if (hsl.z < 0.5)\n" + - " f2 = hsl.z * (1.0 + hsl.y);\n" + - " else\n" + - " f2 = (hsl.z + hsl.y) - (hsl.y * hsl.z);\n" + - - " lowp float f1 = 2.0 * hsl.z - f2;\n" + - - " rgb.r = HueToRGB(f1, f2, hsl.x + (1.0/3.0));\n" + - " rgb.g = HueToRGB(f1, f2, hsl.x);\n" + - " rgb.b= HueToRGB(f1, f2, hsl.x - (1.0/3.0));\n" + - " }\n" + - - " return rgb;\n "+ - "}\n" + - - "lowp float RGBToL(lowp vec3 color)\n" + - "{\n" + - " lowp float fmin = min(min(color.r, color.g), color.b); //Min. value of RGB\n" + - " lowp float fmax = max(max(color.r, color.g), color.b); //Max. value of RGB\n" + - - " return (fmax + fmin) / 2.0; // Luminance\n" + - "}\n" + - - "void main()\n"+ - "{\n"+ - " lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);\n" + - - " // Alternative way:\n" + - " //lowp vec3 lightness = RGBToL(textureColor.rgb);\n" + - " lowp vec3 lightness = textureColor.rgb;\n" + - - " const lowp float a = 0.25;\n" + - " const lowp float b = 0.333;\n" + - " const lowp float scale = 0.7;\n" + - - " lowp vec3 shadows = shadowsShift * (clamp((lightness - b) / -a + 0.5, 0.0, 1.0) * scale);\n" + - " lowp vec3 midtones = midtonesShift * (clamp((lightness - b) / a + 0.5, 0.0, 1.0) *\n" + - " clamp((lightness + b - 1.0) / -a + 0.5, 0.0, 1.0) * scale);\n" + - " lowp vec3 highlights = highlightsShift * (clamp((lightness + b - 1.0) / a + 0.5, 0.0, 1.0) * scale);\n" + - - " mediump vec3 newColor = textureColor.rgb + shadows + midtones + highlights;\n"+ - " newColor = clamp(newColor, 0.0, 1.0);\n "+ - - " if (preserveLuminosity != 0) {\n "+ - " lowp vec3 newHSL = RGBToHSL(newColor);\n" + - " lowp float oldLum = RGBToL(textureColor.rgb);\n" + - " textureColor.rgb = HSLToRGB(vec3(newHSL.x, newHSL.y, oldLum));\n" + - " gl_FragColor = textureColor;\n" + - " } else {\n" + - " gl_FragColor = vec4(newColor.rgb, textureColor.w);\n" + - " }\n" + - "}\n"; - - private int mShadowsLocation; - private int mMidtonesLocation; - private int mHighlightsLocation; - private int mPreserveLuminosityLocation; - - private float[] showdows; - private float[] midtones; - private float[] highlights; - private boolean preserveLuminosity; - - - public GPUImageColorBalanceFilter() { - super(NO_FILTER_VERTEX_SHADER, GPU_IMAGE_COLOR_BALANCE_FRAGMENT_SHADER); - this.showdows = new float[]{0.0f, 0.0f, 0.0f}; - this.midtones = new float[]{0.0f, 0.0f, 0.0f}; - this.highlights = new float[]{0.0f, 0.0f, 0.0f}; - this.preserveLuminosity = true; - } - - @Override - public void onInit() { - super.onInit(); - mShadowsLocation = GLES20.glGetUniformLocation(getProgram(), "shadowsShift"); - mMidtonesLocation = GLES20.glGetUniformLocation(getProgram(), "midtonesShift"); - mHighlightsLocation = GLES20.glGetUniformLocation(getProgram(), "highlightsShift"); - mPreserveLuminosityLocation = GLES20.glGetUniformLocation(getProgram(), "preserveLuminosity"); - } - - @Override - public void onInitialized() { - super.onInitialized(); - setMidtones(this.midtones); - setShowdows(this.showdows); - setHighlights(this.highlights); - setPreserveLuminosity(this.preserveLuminosity); - } - - public void setShowdows(float[] showdows) { - this.showdows = showdows; - setFloatVec3(mShadowsLocation, showdows); - } - - public void setMidtones(float[] midtones) { - this.midtones = midtones; - setFloatVec3(mMidtonesLocation, midtones); - } - - public void setHighlights(float[] highlights) { - this.highlights = highlights; - setFloatVec3(mHighlightsLocation, highlights); - } - - public void setPreserveLuminosity(boolean preserveLuminosity) { - this.preserveLuminosity = preserveLuminosity; - setInteger(mPreserveLuminosityLocation, preserveLuminosity ? 1: 0); - } -} diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageHueFilter.java b/library/src/jp/co/cyberagent/android/gpuimage/GPUImageHueFilter.java deleted file mode 100644 index 9fcf79396..000000000 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageHueFilter.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2012 CyberAgent - * - * 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 jp.co.cyberagent.android.gpuimage; - -import android.opengl.GLES20; - -public class GPUImageHueFilter extends GPUImageFilter { - public static final String HUE_FRAGMENT_SHADER = "" + - "precision highp float;\n" + - "varying highp vec2 textureCoordinate;\n" + - "\n" + - "uniform sampler2D inputImageTexture;\n" + - "uniform mediump float hueAdjust;\n" + - "const highp vec4 kRGBToYPrime = vec4 (0.299, 0.587, 0.114, 0.0);\n" + - "const highp vec4 kRGBToI = vec4 (0.595716, -0.274453, -0.321263, 0.0);\n" + - "const highp vec4 kRGBToQ = vec4 (0.211456, -0.522591, 0.31135, 0.0);\n" + - "\n" + - "const highp vec4 kYIQToR = vec4 (1.0, 0.9563, 0.6210, 0.0);\n" + - "const highp vec4 kYIQToG = vec4 (1.0, -0.2721, -0.6474, 0.0);\n" + - "const highp vec4 kYIQToB = vec4 (1.0, -1.1070, 1.7046, 0.0);\n" + - "\n" + - "void main ()\n" + - "{\n" + - " // Sample the input pixel\n" + - " highp vec4 color = texture2D(inputImageTexture, textureCoordinate);\n" + - "\n" + - " // Convert to YIQ\n" + - " highp float YPrime = dot (color, kRGBToYPrime);\n" + - " highp float I = dot (color, kRGBToI);\n" + - " highp float Q = dot (color, kRGBToQ);\n" + - "\n" + - " // Calculate the hue and chroma\n" + - " highp float hue = atan (Q, I);\n" + - " highp float chroma = sqrt (I * I + Q * Q);\n" + - "\n" + - " // Make the user's adjustments\n" + - " hue += (-hueAdjust); //why negative rotation?\n" + - "\n" + - " // Convert back to YIQ\n" + - " Q = chroma * sin (hue);\n" + - " I = chroma * cos (hue);\n" + - "\n" + - " // Convert back to RGB\n" + - " highp vec4 yIQ = vec4 (YPrime, I, Q, 0.0);\n" + - " color.r = dot (yIQ, kYIQToR);\n" + - " color.g = dot (yIQ, kYIQToG);\n" + - " color.b = dot (yIQ, kYIQToB);\n" + - "\n" + - " // Save the result\n" + - " gl_FragColor = color;\n" + - "}\n"; - - private float mHue; - private int mHueLocation; - - public GPUImageHueFilter() { - this(90.0f); - } - - public GPUImageHueFilter(final float hue) { - super(NO_FILTER_VERTEX_SHADER, HUE_FRAGMENT_SHADER); - mHue = hue; - } - - @Override - public void onInit() { - super.onInit(); - mHueLocation = GLES20.glGetUniformLocation(getProgram(), "hueAdjust"); - } - - @Override - public void onInitialized() { - super.onInitialized(); - setHue(mHue); - } - - public void setHue(final float hue) { - mHue = hue; - float hueAdjust = (mHue % 360.0f) * (float) Math.PI / 180.0f; - setFloat(mHueLocation, hueAdjust); - } -} diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageLevelsFilter.java b/library/src/jp/co/cyberagent/android/gpuimage/GPUImageLevelsFilter.java deleted file mode 100644 index d7fbcfdfe..000000000 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageLevelsFilter.java +++ /dev/null @@ -1,130 +0,0 @@ -package jp.co.cyberagent.android.gpuimage; - -import android.opengl.GLES20; -import android.util.Log; - -/** - * Created by vashisthg 30/05/14. - */ -public class GPUImageLevelsFilter extends GPUImageFilter{ - - private static final String LOGTAG = GPUImageLevelsFilter.class.getSimpleName(); - - public static final String LEVELS_FRAGMET_SHADER = - - " varying highp vec2 textureCoordinate;\n" + - " \n" + - " uniform sampler2D inputImageTexture;\n" + - " uniform mediump vec3 levelMinimum;\n" + - " uniform mediump vec3 levelMiddle;\n" + - " uniform mediump vec3 levelMaximum;\n" + - " uniform mediump vec3 minOutput;\n" + - " uniform mediump vec3 maxOutput;\n" + - " \n" + - " void main()\n" + - " {\n" + - " mediump vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);\n" + - " \n" + - " gl_FragColor = vec4( mix(minOutput, maxOutput, pow(min(max(textureColor.rgb -levelMinimum, vec3(0.0)) / (levelMaximum - levelMinimum ), vec3(1.0)), 1.0 /levelMiddle)) , textureColor.a);\n" + - " }\n"; - - private int mMinLocation; - private float[] mMin; - private int mMidLocation; - private float[] mMid; - private int mMaxLocation; - private float[] mMax; - private int mMinOutputLocation; - private float[] mMinOutput; - private int mMaxOutputLocation; - private float[] mMaxOutput; - - public GPUImageLevelsFilter() { - this(new float[] {0.0f,0.0f,0.0f}, new float[] {1.0f, 1.0f, 1.0f }, new float[] {1.0f, 1.0f ,1.0f}, new float[] {0.0f, 0.0f, 0.0f}, new float[] {1.0f,1.0f,1.0f}); - } - - private GPUImageLevelsFilter(final float[] min, final float[] mid, final float[] max, final float[] minOUt, final float[] maxOut) { - super(NO_FILTER_VERTEX_SHADER, LEVELS_FRAGMET_SHADER); - - mMin = min; - mMid = mid; - mMax = max; - mMinOutput = minOUt; - mMaxOutput = maxOut; - setMin(0.0f, 1.0f, 1.0f, 0.0f, 1.0f); - } - - @Override - public void onInit() { - super.onInit(); - mMinLocation = GLES20.glGetUniformLocation(getProgram(), "levelMinimum"); - mMidLocation = GLES20.glGetUniformLocation(getProgram(), "levelMiddle"); - mMaxLocation = GLES20.glGetUniformLocation(getProgram(), "levelMaximum"); - mMinOutputLocation = GLES20.glGetUniformLocation(getProgram(), "minOutput"); - mMaxOutputLocation = GLES20.glGetUniformLocation(getProgram(), "maxOutput"); - } - - @Override - public void onInitialized() { - super.onInitialized(); - updateUniforms(); - } - - - public void updateUniforms () { - setFloatVec3(mMinLocation, mMin); - setFloatVec3(mMidLocation, mMid); - setFloatVec3(mMaxLocation, mMax); - setFloatVec3(mMinOutputLocation, mMinOutput); - setFloatVec3(mMaxOutputLocation, mMaxOutput); - } - - public void setMin(float min, float mid , float max ,float minOut , float maxOut) { - setRedMin(min, mid, max, minOut, maxOut); - setGreenMin(min, mid, max, minOut, maxOut); - setBlueMin(min, mid, max, minOut, maxOut); - } - - public void setMin(float min, float mid , float max ) { - setMin(min, mid, max, 0.0f, 1.0f); - } - - public void setRedMin(float min, float mid , float max ,float minOut , float maxOut) { - mMin[0] = min; - mMid[0] = mid; - mMax[0] = max; - mMinOutput[0] = minOut; - mMaxOutput[0] = maxOut; - updateUniforms(); - } - - public void setRedMin(float min, float mid , float max ){ - setRedMin(min, mid, max, 0, 1); - } - - public void setGreenMin(float min, float mid , float max ,float minOut , float maxOut) { - mMin[1] = min; - mMid[1] = mid; - mMax[1] = max; - mMinOutput[1] = minOut; - mMaxOutput[1] = maxOut; - updateUniforms(); - } - - public void setGreenMin(float min, float mid , float max ){ - setGreenMin(min, mid, max, 0, 1); - } - - public void setBlueMin(float min, float mid , float max ,float minOut , float maxOut) { - mMin[2] = min; - mMid[2] = mid; - mMax[2] = max; - mMinOutput[2] = minOut; - mMaxOutput[2] = maxOut; - updateUniforms(); - } - - public void setBlueMin(float min, float mid , float max ){ - setBlueMin(min, mid, max, 0, 1); - } -} diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageRGBFilter.java b/library/src/jp/co/cyberagent/android/gpuimage/GPUImageRGBFilter.java deleted file mode 100644 index f0af18cb9..000000000 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageRGBFilter.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2012 CyberAgent - * - * 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 jp.co.cyberagent.android.gpuimage; - -import android.opengl.GLES20; - -/** - * Adjusts the individual RGB channels of an image - * red: Normalized values by which each color channel is multiplied. The range is from 0.0 up, with 1.0 as the default. - * green: - * blue: - */ -public class GPUImageRGBFilter extends GPUImageFilter { - public static final String RGB_FRAGMENT_SHADER = "" + - " varying highp vec2 textureCoordinate;\n" + - " \n" + - " uniform sampler2D inputImageTexture;\n" + - " uniform highp float red;\n" + - " uniform highp float green;\n" + - " uniform highp float blue;\n" + - " \n" + - " void main()\n" + - " {\n" + - " highp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);\n" + - " \n" + - " gl_FragColor = vec4(textureColor.r * red, textureColor.g * green, textureColor.b * blue, 1.0);\n" + - " }\n"; - - private int mRedLocation; - private float mRed; - private int mGreenLocation; - private float mGreen; - private int mBlueLocation; - private float mBlue; - private boolean mIsInitialized = false; - - public GPUImageRGBFilter() { - this(1.0f, 1.0f, 1.0f); - } - - public GPUImageRGBFilter(final float red, final float green, final float blue) { - super(NO_FILTER_VERTEX_SHADER, RGB_FRAGMENT_SHADER); - mRed = red; - mGreen = green; - mBlue = blue; - } - - @Override - public void onInit() { - super.onInit(); - mRedLocation = GLES20.glGetUniformLocation(getProgram(), "red"); - mGreenLocation = GLES20.glGetUniformLocation(getProgram(), "green"); - mBlueLocation = GLES20.glGetUniformLocation(getProgram(), "blue"); - mIsInitialized = true; - setRed(mRed); - setGreen(mGreen); - setBlue(mBlue); - } - - public void setRed(final float red) { - mRed = red; - if (mIsInitialized) { - setFloat(mRedLocation, mRed); - } - } - - public void setGreen(final float green) { - mGreen = green; - if (mIsInitialized) { - setFloat(mGreenLocation, mGreen); - } - } - - public void setBlue(final float blue) { - mBlue = blue; - if (mIsInitialized) { - setFloat(mBlueLocation, mBlue); - } - } -} diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageSobelThresholdFilter.java b/library/src/jp/co/cyberagent/android/gpuimage/GPUImageSobelThresholdFilter.java deleted file mode 100644 index f1dcf64e7..000000000 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageSobelThresholdFilter.java +++ /dev/null @@ -1,74 +0,0 @@ -package jp.co.cyberagent.android.gpuimage; - -import android.opengl.GLES20; - -public class GPUImageSobelThresholdFilter extends - GPUImage3x3TextureSamplingFilter { - public static final String SOBEL_THRESHOLD_EDGE_DETECTION = "" + - "precision mediump float;\n" + - "\n" + - "varying vec2 textureCoordinate;\n" + - "varying vec2 leftTextureCoordinate;\n" + - "varying vec2 rightTextureCoordinate;\n" + - "\n" + - "varying vec2 topTextureCoordinate;\n" + - "varying vec2 topLeftTextureCoordinate;\n" + - "varying vec2 topRightTextureCoordinate;\n" + - "\n" + - "varying vec2 bottomTextureCoordinate;\n" + - "varying vec2 bottomLeftTextureCoordinate;\n" + - "varying vec2 bottomRightTextureCoordinate;\n" + - "\n" + - "uniform sampler2D inputImageTexture;\n" + - "uniform lowp float threshold;\n" + - "\n" + - "const highp vec3 W = vec3(0.2125, 0.7154, 0.0721);\n" + - "\n" + - "void main()\n" + - "{\n" + - " float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r;\n" + - " float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r;\n" + - " float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r;\n" + - " float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r;\n" + - " float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r;\n" + - " float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r;\n" + - " float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r;\n" + - " float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r;\n" + - " float h = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + bottomLeftIntensity + 2.0 * bottomIntensity + bottomRightIntensity;\n" + - " float v = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomRightIntensity + 2.0 * rightIntensity + topRightIntensity;\n" + - "\n" + - " float mag = 1.0 - length(vec2(h, v));\n" + - " mag = step(threshold, mag);\n" + - "\n" + - " gl_FragColor = vec4(vec3(mag), 1.0);\n" + - "}\n"; - - private int mUniformThresholdLocation; - private float mThreshold = 0.9f; - - public GPUImageSobelThresholdFilter() { - this(0.9f); - } - - public GPUImageSobelThresholdFilter(float threshold) { - super(SOBEL_THRESHOLD_EDGE_DETECTION); - mThreshold = threshold; - } - - @Override - public void onInit() { - super.onInit(); - mUniformThresholdLocation = GLES20.glGetUniformLocation(getProgram(), "threshold"); - } - - @Override - public void onInitialized() { - super.onInitialized(); - setThreshold(mThreshold); - } - - public void setThreshold(final float threshold) { - mThreshold = threshold; - setFloat(mUniformThresholdLocation, threshold); - } -} diff --git a/library/src/main/AndroidManifest.xml b/library/src/main/AndroidManifest.xml new file mode 100644 index 000000000..5193400f6 --- /dev/null +++ b/library/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/library/src/main/cpp/CMakeLists.txt b/library/src/main/cpp/CMakeLists.txt new file mode 100644 index 000000000..af48ac017 --- /dev/null +++ b/library/src/main/cpp/CMakeLists.txt @@ -0,0 +1,46 @@ +# 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. + +add_library( # Sets the name of the library. + yuv-decoder + + # Sets the library as a shared library. + SHARED + + # Provides a relative path to your source file(s). + yuv-decoder.c) + +# 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. + yuv-decoder + + # Links the target library to the log library + # included in the NDK. + ${log-lib} + GLESv2 + jnigraphics) \ No newline at end of file diff --git a/library/src/main/cpp/yuv-decoder.c b/library/src/main/cpp/yuv-decoder.c new file mode 100644 index 000000000..b9596f85c --- /dev/null +++ b/library/src/main/cpp/yuv-decoder.c @@ -0,0 +1,158 @@ +#include + +#include +#include + + +JNIEXPORT void JNICALL +Java_jp_co_cyberagent_android_gpuimage_GPUImageNativeLibrary_YUVtoRBGA(JNIEnv *env, jobject obj, + jbyteArray yuv420sp, + jint width, jint height, + jintArray rgbOut) { + int sz; + int i; + int j; + int Y; + int Cr = 0; + int Cb = 0; + int pixPtr = 0; + int jDiv2 = 0; + int R = 0; + int G = 0; + int B = 0; + int cOff; + int w = width; + int h = height; + sz = w * h; + + jint *rgbData = (jint *) ((*env)->GetPrimitiveArrayCritical(env, rgbOut, 0)); + jbyte *yuv = (jbyte *) (*env)->GetPrimitiveArrayCritical(env, yuv420sp, 0); + + for (j = 0; j < h; j++) { + pixPtr = j * w; + jDiv2 = j >> 1; + for (i = 0; i < w; i++) { + Y = yuv[pixPtr]; + if (Y < 0) Y += 255; + if ((i & 0x1) != 1) { + cOff = sz + jDiv2 * w + (i >> 1) * 2; + Cb = yuv[cOff]; + if (Cb < 0) Cb += 127; else Cb -= 128; + Cr = yuv[cOff + 1]; + if (Cr < 0) Cr += 127; else Cr -= 128; + } + + //ITU-R BT.601 conversion + // + //R = 1.164*(Y-16) + 2.018*(Cr-128); + //G = 1.164*(Y-16) - 0.813*(Cb-128) - 0.391*(Cr-128); + //B = 1.164*(Y-16) + 1.596*(Cb-128); + // + Y = Y + (Y >> 3) + (Y >> 5) + (Y >> 7); + R = Y + (Cr << 1) + (Cr >> 6); + if (R < 0) R = 0; else if (R > 255) R = 255; + G = Y - Cb + (Cb >> 3) + (Cb >> 4) - (Cr >> 1) + (Cr >> 3); + if (G < 0) G = 0; else if (G > 255) G = 255; + B = Y + Cb + (Cb >> 1) + (Cb >> 4) + (Cb >> 5); + if (B < 0) B = 0; else if (B > 255) B = 255; + rgbData[pixPtr++] = 0xff000000 + (R << 16) + (G << 8) + B; + } + } + + (*env)->ReleasePrimitiveArrayCritical(env, rgbOut, rgbData, 0); + (*env)->ReleasePrimitiveArrayCritical(env, yuv420sp, yuv, 0); +} + +JNIEXPORT void JNICALL +Java_jp_co_cyberagent_android_gpuimage_GPUImageNativeLibrary_YUVtoARBG(JNIEnv *env, jobject obj, + jbyteArray yuv420sp, + jint width, jint height, + jintArray rgbOut) { + int sz; + int i; + int j; + int Y; + int Cr = 0; + int Cb = 0; + int pixPtr = 0; + int jDiv2 = 0; + int R = 0; + int G = 0; + int B = 0; + int cOff; + int w = width; + int h = height; + sz = w * h; + + jint *rgbData = (jint *) ((*env)->GetPrimitiveArrayCritical(env, rgbOut, 0)); + jbyte *yuv = (jbyte *) (*env)->GetPrimitiveArrayCritical(env, yuv420sp, 0); + + for (j = 0; j < h; j++) { + pixPtr = j * w; + jDiv2 = j >> 1; + for (i = 0; i < w; i++) { + Y = yuv[pixPtr]; + if (Y < 0) Y += 255; + if ((i & 0x1) != 1) { + cOff = sz + jDiv2 * w + (i >> 1) * 2; + Cb = yuv[cOff]; + if (Cb < 0) Cb += 127; else Cb -= 128; + Cr = yuv[cOff + 1]; + if (Cr < 0) Cr += 127; else Cr -= 128; + } + + //ITU-R BT.601 conversion + // + //R = 1.164*(Y-16) + 2.018*(Cr-128); + //G = 1.164*(Y-16) - 0.813*(Cb-128) - 0.391*(Cr-128); + //B = 1.164*(Y-16) + 1.596*(Cb-128); + // + Y = Y + (Y >> 3) + (Y >> 5) + (Y >> 7); + R = Y + (Cr << 1) + (Cr >> 6); + if (R < 0) R = 0; else if (R > 255) R = 255; + G = Y - Cb + (Cb >> 3) + (Cb >> 4) - (Cr >> 1) + (Cr >> 3); + if (G < 0) G = 0; else if (G > 255) G = 255; + B = Y + Cb + (Cb >> 1) + (Cb >> 4) + (Cb >> 5); + if (B < 0) B = 0; else if (B > 255) B = 255; + rgbData[pixPtr++] = 0xff000000 + (B << 16) + (G << 8) + R; + } + } + + (*env)->ReleasePrimitiveArrayCritical(env, rgbOut, rgbData, 0); + (*env)->ReleasePrimitiveArrayCritical(env, yuv420sp, yuv, 0); +} + + +JNIEXPORT void JNICALL +Java_jp_co_cyberagent_android_gpuimage_GPUImageNativeLibrary_adjustBitmap(JNIEnv *jenv, jclass thiz, + jobject src) { + unsigned char *srcByteBuffer; + int result = 0; + int i, j; + AndroidBitmapInfo srcInfo; + + result = AndroidBitmap_getInfo(jenv, src, &srcInfo); + if (result != ANDROID_BITMAP_RESULT_SUCCESS) { + return; + } + + result = AndroidBitmap_lockPixels(jenv, src, (void **) &srcByteBuffer); + if (result != ANDROID_BITMAP_RESULT_SUCCESS) { + return; + } + + int width = srcInfo.width; + int height = srcInfo.height; + glReadPixels(0, 0, srcInfo.width, srcInfo.height, GL_RGBA, GL_UNSIGNED_BYTE, srcByteBuffer); + + int *pIntBuffer = (int *) srcByteBuffer; + + for (i = 0; i < height / 2; i++) { + for (j = 0; j < width; j++) { + int temp = pIntBuffer[(height - i - 1) * width + j]; + pIntBuffer[(height - i - 1) * width + j] = pIntBuffer[i * width + j]; + pIntBuffer[i * width + j] = temp; + } + } + AndroidBitmap_unlockPixels(jenv, src); +} \ No newline at end of file diff --git a/library/src/main/java/jp/co/cyberagent/android/gpuimage/GLTextureView.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/GLTextureView.java new file mode 100644 index 000000000..d6cfc0784 --- /dev/null +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/GLTextureView.java @@ -0,0 +1,1809 @@ +package jp.co.cyberagent.android.gpuimage; + +import android.content.Context; +import android.graphics.SurfaceTexture; +import android.opengl.GLDebugHelper; +import android.util.AttributeSet; +import android.util.Log; +import android.view.TextureView; +import android.view.View; + +import java.io.Writer; +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.List; + +import javax.microedition.khronos.egl.EGL10; +import javax.microedition.khronos.egl.EGL11; +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.egl.EGLContext; +import javax.microedition.khronos.egl.EGLDisplay; +import javax.microedition.khronos.egl.EGLSurface; +import javax.microedition.khronos.opengles.GL; +import javax.microedition.khronos.opengles.GL10; + +/* + * Copyright (C) 2018 Wasabeef + * + * 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. + */ +public class GLTextureView extends TextureView + implements TextureView.SurfaceTextureListener, View.OnLayoutChangeListener { + + private final static String TAG = GLTextureView.class.getSimpleName(); + + private final static boolean LOG_ATTACH_DETACH = false; + private final static boolean LOG_THREADS = false; + private final static boolean LOG_PAUSE_RESUME = false; + private final static boolean LOG_SURFACE = false; + private final static boolean LOG_RENDERER = false; + private final static boolean LOG_RENDERER_DRAW_FRAME = false; + private final static boolean LOG_EGL = false; + + /** + * The renderer only renders + * when the surface is created, or when {@link #requestRender} is called. + * + * @see #getRenderMode() + * @see #setRenderMode(int) + * @see #requestRender() + */ + public final static int RENDERMODE_WHEN_DIRTY = 0; + /** + * The renderer is called + * continuously to re-render the scene. + * + * @see #getRenderMode() + * @see #setRenderMode(int) + */ + public final static int RENDERMODE_CONTINUOUSLY = 1; + + /** + * Check glError() after every GL call and throw an exception if glError indicates + * that an error has occurred. This can be used to help track down which OpenGL ES call + * is causing an error. + * + * @see #getDebugFlags + * @see #setDebugFlags + */ + public final static int DEBUG_CHECK_GL_ERROR = 1; + + /** + * Log GL calls to the system log at "verbose" level with tag "GLTextureView". + * + * @see #getDebugFlags + * @see #setDebugFlags + */ + public final static int DEBUG_LOG_GL_CALLS = 2; + + /** + * Standard View constructor. In order to render something, you + * must call {@link #setRenderer} to register a renderer. + */ + public GLTextureView(Context context) { + super(context); + init(); + } + + /** + * Standard View constructor. In order to render something, you + * must call {@link #setRenderer} to register a renderer. + */ + public GLTextureView(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + @Override + protected void finalize() throws Throwable { + try { + if (glThread != null) { + // GLThread may still be running if this view was never + // attached to a window. + glThread.requestExitAndWait(); + } + } finally { + super.finalize(); + } + } + + private void init() { + setSurfaceTextureListener(this); + } + + /** + * Set the glWrapper. If the glWrapper is not null, its + * {@link GLWrapper#wrap(javax.microedition.khronos.opengles.GL)} method is called + * whenever a surface is created. A GLWrapper can be used to wrap + * the GL object that's passed to the renderer. Wrapping a GL + * object enables examining and modifying the behavior of the + * GL calls made by the renderer. + *

+ * Wrapping is typically used for debugging purposes. + *

+ * The default value is null. + * + * @param glWrapper the new GLWrapper + */ + public void setGLWrapper(GLWrapper glWrapper) { + this.glWrapper = glWrapper; + } + + /** + * Set the debug flags to a new value. The value is + * constructed by OR-together zero or more + * of the DEBUG_CHECK_* constants. The debug flags take effect + * whenever a surface is created. The default value is zero. + * + * @param debugFlags the new debug flags + * @see #DEBUG_CHECK_GL_ERROR + * @see #DEBUG_LOG_GL_CALLS + */ + public void setDebugFlags(int debugFlags) { + this.debugFlags = debugFlags; + } + + /** + * Get the current value of the debug flags. + * + * @return the current value of the debug flags. + */ + public int getDebugFlags() { + return debugFlags; + } + + /** + * Control whether the EGL context is preserved when the GLTextureView is paused and + * resumed. + *

+ * If set to true, then the EGL context may be preserved when the GLTextureView is paused. + * Whether the EGL context is actually preserved or not depends upon whether the + * Android device that the program is running on can support an arbitrary number of EGL + * contexts or not. Devices that can only support a limited number of EGL contexts must + * release the EGL context in order to allow multiple applications to share the GPU. + *

+ * If set to false, the EGL context will be released when the GLTextureView is paused, + * and recreated when the GLTextureView is resumed. + *

+ *

+ * The default is false. + * + * @param preserveOnPause preserve the EGL context when paused + */ + public void setPreserveEGLContextOnPause(boolean preserveOnPause) { + preserveEGLContextOnPause = preserveOnPause; + } + + /** + * @return true if the EGL context will be preserved when paused + */ + public boolean getPreserveEGLContextOnPause() { + return preserveEGLContextOnPause; + } + + /** + * Set the renderer associated with this view. Also starts the thread that + * will call the renderer, which in turn causes the rendering to start. + *

This method should be called once and only once in the life-cycle of + * a GLTextureView. + *

The following GLTextureView methods can only be called before + * setRenderer is called: + *

    + *
  • {@link #setEGLConfigChooser(boolean)} + *
  • {@link #setEGLConfigChooser(EGLConfigChooser)} + *
  • {@link #setEGLConfigChooser(int, int, int, int, int, int)} + *
+ *

+ * The following GLTextureView methods can only be called after + * setRenderer is called: + *

    + *
  • {@link #getRenderMode()} + *
  • {@link #onPause()} + *
  • {@link #onResume()} + *
  • {@link #queueEvent(Runnable)} + *
  • {@link #requestRender()} + *
  • {@link #setRenderMode(int)} + *
+ * + * @param renderer the renderer to use to perform OpenGL drawing. + */ + public void setRenderer(Renderer renderer) { + checkRenderThreadState(); + if (eglConfigChooser == null) { + eglConfigChooser = new SimpleEGLConfigChooser(true); + } + if (eglContextFactory == null) { + eglContextFactory = new DefaultContextFactory(); + } + if (eglWindowSurfaceFactory == null) { + eglWindowSurfaceFactory = new DefaultWindowSurfaceFactory(); + } + this.renderer = renderer; + glThread = new GLThread(mThisWeakRef); + glThread.start(); + } + + /** + * Install a custom EGLContextFactory. + *

If this method is + * called, it must be called before {@link #setRenderer(Renderer)} + * is called. + *

+ * If this method is not called, then by default + * a context will be created with no shared context and + * with a null attribute list. + */ + public void setEGLContextFactory(EGLContextFactory factory) { + checkRenderThreadState(); + eglContextFactory = factory; + } + + /** + * Install a custom EGLWindowSurfaceFactory. + *

If this method is + * called, it must be called before {@link #setRenderer(Renderer)} + * is called. + *

+ * If this method is not called, then by default + * a window surface will be created with a null attribute list. + */ + public void setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory factory) { + checkRenderThreadState(); + eglWindowSurfaceFactory = factory; + } + + /** + * Install a custom EGLConfigChooser. + *

If this method is + * called, it must be called before {@link #setRenderer(Renderer)} + * is called. + *

+ * If no setEGLConfigChooser method is called, then by default the + * view will choose an EGLConfig that is compatible with the current + * android.view.Surface, with a depth buffer depth of + * at least 16 bits. + */ + public void setEGLConfigChooser(EGLConfigChooser configChooser) { + checkRenderThreadState(); + eglConfigChooser = configChooser; + } + + /** + * Install a config chooser which will choose a config + * as close to 16-bit RGB as possible, with or without an optional depth + * buffer as close to 16-bits as possible. + *

If this method is + * called, it must be called before {@link #setRenderer(Renderer)} + * is called. + *

+ * If no setEGLConfigChooser method is called, then by default the + * view will choose an RGB_888 surface with a depth buffer depth of + * at least 16 bits. + */ + public void setEGLConfigChooser(boolean needDepth) { + setEGLConfigChooser(new SimpleEGLConfigChooser(needDepth)); + } + + /** + * Install a config chooser which will choose a config + * with at least the specified depthSize and stencilSize, + * and exactly the specified redSize, greenSize, blueSize and alphaSize. + *

If this method is + * called, it must be called before {@link #setRenderer(Renderer)} + * is called. + *

+ * If no setEGLConfigChooser method is called, then by default the + * view will choose an RGB_888 surface with a depth buffer depth of + * at least 16 bits. + */ + public void setEGLConfigChooser(int redSize, int greenSize, int blueSize, int alphaSize, + int depthSize, int stencilSize) { + setEGLConfigChooser( + new ComponentSizeChooser(redSize, greenSize, blueSize, alphaSize, depthSize, stencilSize)); + } + + /** + * Inform the default EGLContextFactory and default EGLConfigChooser + * which EGLContext client version to pick. + *

Use this method to create an OpenGL ES 2.0-compatible context. + * Example: + *

+     * public MyView(Context context) {
+     * super(context);
+     * setEGLContextClientVersion(2); // Pick an OpenGL ES 2.0 context.
+     * setRenderer(new MyRenderer());
+     * }
+     * 
+ *

Note: Activities which require OpenGL ES 2.0 should indicate this by + * setting @lt;uses-feature android:glEsVersion="0x00020000" /> in the activity's + * AndroidManifest.xml file. + *

If this method is called, it must be called before {@link #setRenderer(Renderer)} + * is called. + *

This method only affects the behavior of the default EGLContexFactory and the + * default EGLConfigChooser. If + * {@link #setEGLContextFactory(EGLContextFactory)} has been called, then the supplied + * EGLContextFactory is responsible for creating an OpenGL ES 2.0-compatible context. + * If + * {@link #setEGLConfigChooser(EGLConfigChooser)} has been called, then the supplied + * EGLConfigChooser is responsible for choosing an OpenGL ES 2.0-compatible config. + * + * @param version The EGLContext client version to choose. Use 2 for OpenGL ES 2.0 + */ + public void setEGLContextClientVersion(int version) { + checkRenderThreadState(); + eglContextClientVersion = version; + } + + /** + * Set the rendering mode. When renderMode is + * RENDERMODE_CONTINUOUSLY, the renderer is called + * repeatedly to re-render the scene. When renderMode + * is RENDERMODE_WHEN_DIRTY, the renderer only rendered when the surface + * is created, or when {@link #requestRender} is called. Defaults to RENDERMODE_CONTINUOUSLY. + *

+ * Using RENDERMODE_WHEN_DIRTY can improve battery life and overall system performance + * by allowing the GPU and CPU to idle when the view does not need to be updated. + *

+ * This method can only be called after {@link #setRenderer(Renderer)} + * + * @param renderMode one of the RENDERMODE_X constants + * @see #RENDERMODE_CONTINUOUSLY + * @see #RENDERMODE_WHEN_DIRTY + */ + public void setRenderMode(int renderMode) { + glThread.setRenderMode(renderMode); + } + + /** + * Get the current rendering mode. May be called + * from any thread. Must not be called before a renderer has been set. + * + * @return the current rendering mode. + * @see #RENDERMODE_CONTINUOUSLY + * @see #RENDERMODE_WHEN_DIRTY + */ + public int getRenderMode() { + return glThread.getRenderMode(); + } + + /** + * Request that the renderer render a frame. + * This method is typically used when the render mode has been set to + * {@link #RENDERMODE_WHEN_DIRTY}, so that frames are only rendered on demand. + * May be called + * from any thread. Must not be called before a renderer has been set. + */ + public void requestRender() { + glThread.requestRender(); + } + + /** + * This method is part of the SurfaceHolder.Callback interface, and is + * not normally called or subclassed by clients of GLTextureView. + */ + public void surfaceCreated(SurfaceTexture texture) { + glThread.surfaceCreated(); + } + + /** + * This method is part of the SurfaceHolder.Callback interface, and is + * not normally called or subclassed by clients of GLTextureView. + */ + public void surfaceDestroyed(SurfaceTexture texture) { + // Surface will be destroyed when we return + glThread.surfaceDestroyed(); + } + + /** + * This method is part of the SurfaceHolder.Callback interface, and is + * not normally called or subclassed by clients of GLTextureView. + */ + public void surfaceChanged(SurfaceTexture texture, int format, int w, int h) { + glThread.onWindowResize(w, h); + } + + /** + * Inform the view that the activity is paused. The owner of this view must + * call this method when the activity is paused. Calling this method will + * pause the rendering thread. + * Must not be called before a renderer has been set. + */ + public void onPause() { + glThread.onPause(); + } + + /** + * Inform the view that the activity is resumed. The owner of this view must + * call this method when the activity is resumed. Calling this method will + * recreate the OpenGL display and resume the rendering + * thread. + * Must not be called before a renderer has been set. + */ + public void onResume() { + glThread.onResume(); + } + + /** + * Queue a runnable to be run on the GL rendering thread. This can be used + * to communicate with the Renderer on the rendering thread. + * Must not be called before a renderer has been set. + * + * @param r the runnable to be run on the GL rendering thread. + */ + public void queueEvent(Runnable r) { + glThread.queueEvent(r); + } + + /** + * This method is used as part of the View class and is not normally + * called or subclassed by clients of GLTextureView. + */ + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (LOG_ATTACH_DETACH) { + Log.d(TAG, "onAttachedToWindow reattach =" + detached); + } + if (detached && (renderer != null)) { + int renderMode = RENDERMODE_CONTINUOUSLY; + if (glThread != null) { + renderMode = glThread.getRenderMode(); + } + glThread = new GLThread(mThisWeakRef); + if (renderMode != RENDERMODE_CONTINUOUSLY) { + glThread.setRenderMode(renderMode); + } + glThread.start(); + } + detached = false; + } + + /** + * This method is used as part of the View class and is not normally + * called or subclassed by clients of GLTextureView. + * Must not be called before a renderer has been set. + */ + @Override + protected void onDetachedFromWindow() { + if (LOG_ATTACH_DETACH) { + Log.d(TAG, "onDetachedFromWindow"); + } + if (glThread != null) { + glThread.requestExitAndWait(); + } + detached = true; + super.onDetachedFromWindow(); + } + + public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, + int oldTop, int oldRight, int oldBottom) { + surfaceChanged(getSurfaceTexture(), 0, right - left, bottom - top); + } + + public void addSurfaceTextureListener(SurfaceTextureListener listener) { + surfaceTextureListeners.add(listener); + } + + public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { + surfaceCreated(surface); + surfaceChanged(surface, 0, width, height); + + for (SurfaceTextureListener l : surfaceTextureListeners) { + l.onSurfaceTextureAvailable(surface, width, height); + } + } + + public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { + surfaceChanged(surface, 0, width, height); + + for (SurfaceTextureListener l : surfaceTextureListeners) { + l.onSurfaceTextureSizeChanged(surface, width, height); + } + } + + public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { + surfaceDestroyed(surface); + + for (SurfaceTextureListener l : surfaceTextureListeners) { + l.onSurfaceTextureDestroyed(surface); + } + + return true; + } + + public void onSurfaceTextureUpdated(SurfaceTexture surface) { + requestRender(); + + for (SurfaceTextureListener l : surfaceTextureListeners) { + l.onSurfaceTextureUpdated(surface); + } + } + + // ---------------------------------------------------------------------- + + /** + * An interface used to wrap a GL interface. + *

Typically + * used for implementing debugging and tracing on top of the default + * GL interface. You would typically use this by creating your own class + * that implemented all the GL methods by delegating to another GL instance. + * Then you could add your own behavior before or after calling the + * delegate. All the GLWrapper would do was instantiate and return the + * wrapper GL instance: + *

+     * class MyGLWrapper implements GLWrapper {
+     * GL wrap(GL gl) {
+     * return new MyGLImplementation(gl);
+     * }
+     * static class MyGLImplementation implements GL,GL10,GL11,... {
+     * ...
+     * }
+     * }
+     * 
+ * + * @see #setGLWrapper(GLWrapper) + */ + public interface GLWrapper { + /** + * Wraps a gl interface in another gl interface. + * + * @param gl a GL interface that is to be wrapped. + * @return either the input argument or another GL object that wraps the input argument. + */ + GL wrap(GL gl); + } + + /** + * A generic renderer interface. + *

+ * The renderer is responsible for making OpenGL calls to render a frame. + *

+ * GLTextureView clients typically create their own classes that implement + * this interface, and then call {@link GLTextureView#setRenderer} to + * register the renderer with the GLTextureView. + *

+ * + *

+ *

Developer Guides

+ *

For more information about how to use OpenGL, read the + * OpenGL developer guide.

+ *
+ * + *

Threading

+ * The renderer will be called on a separate thread, so that rendering + * performance is decoupled from the UI thread. Clients typically need to + * communicate with the renderer from the UI thread, because that's where + * input events are received. Clients can communicate using any of the + * standard Java techniques for cross-thread communication, or they can + * use the {@link GLTextureView#queueEvent(Runnable)} convenience method. + *

+ *

EGL Context Lost

+ * There are situations where the EGL rendering context will be lost. This + * typically happens when device wakes up after going to sleep. When + * the EGL context is lost, all OpenGL resources (such as textures) that are + * associated with that context will be automatically deleted. In order to + * keep rendering correctly, a renderer must recreate any lost resources + * that it still needs. The {@link #onSurfaceCreated(javax.microedition.khronos.opengles.GL10, + * javax.microedition.khronos.egl.EGLConfig)} method + * is a convenient place to do this. + * + * @see #setRenderer(Renderer) + */ + public interface Renderer { + /** + * Called when the surface is created or recreated. + *

+ * Called when the rendering thread + * starts and whenever the EGL context is lost. The EGL context will typically + * be lost when the Android device awakes after going to sleep. + *

+ * Since this method is called at the beginning of rendering, as well as + * every time the EGL context is lost, this method is a convenient place to put + * code to create resources that need to be created when the rendering + * starts, and that need to be recreated when the EGL context is lost. + * Textures are an example of a resource that you might want to create + * here. + *

+ * Note that when the EGL context is lost, all OpenGL resources associated + * with that context will be automatically deleted. You do not need to call + * the corresponding "glDelete" methods such as glDeleteTextures to + * manually delete these lost resources. + *

+ * + * @param gl the GL interface. Use instanceof to + * test if the interface supports GL11 or higher interfaces. + * @param config the EGLConfig of the created surface. Can be used + * to create matching pbuffers. + */ + void onSurfaceCreated(GL10 gl, EGLConfig config); + + /** + * Called when the surface changed size. + *

+ * Called after the surface is created and whenever + * the OpenGL ES surface size changes. + *

+ * Typically you will set your viewport here. If your camera + * is fixed then you could also set your projection matrix here: + *

+         * void onSurfaceChanged(GL10 gl, int width, int height) {
+         * gl.glViewport(0, 0, width, height);
+         * // for a fixed camera, set the projection too
+         * float ratio = (float) width / height;
+         * gl.glMatrixMode(GL10.GL_PROJECTION);
+         * gl.glLoadIdentity();
+         * gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
+         * }
+         * 
+ * + * @param gl the GL interface. Use instanceof to + * test if the interface supports GL11 or higher interfaces. + */ + void onSurfaceChanged(GL10 gl, int width, int height); + + /** + * Called to draw the current frame. + *

+ * This method is responsible for drawing the current frame. + *

+ * The implementation of this method typically looks like this: + *

+         * void onDrawFrame(GL10 gl) {
+         * gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
+         * //... other gl calls to render the scene ...
+         * }
+         * 
+ * + * @param gl the GL interface. Use instanceof to + * test if the interface supports GL11 or higher interfaces. + */ + void onDrawFrame(GL10 gl); + } + + /** + * An interface for customizing the eglCreateContext and eglDestroyContext calls. + *

+ * This interface must be implemented by clients wishing to call + * {@link GLTextureView#setEGLContextFactory(EGLContextFactory)} + */ + public interface EGLContextFactory { + EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig); + + void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context); + } + + private class DefaultContextFactory implements EGLContextFactory { + private int EGL_CONTEXT_CLIENT_VERSION = 0x3098; + + public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig config) { + int[] attrib_list = { + EGL_CONTEXT_CLIENT_VERSION, eglContextClientVersion, EGL10.EGL_NONE + }; + + return egl.eglCreateContext(display, config, EGL10.EGL_NO_CONTEXT, + eglContextClientVersion != 0 ? attrib_list : null); + } + + public void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context) { + if (!egl.eglDestroyContext(display, context)) { + Log.e("DefaultContextFactory", "display:" + display + " context: " + context); + if (LOG_THREADS) { + Log.i("DefaultContextFactory", "tid=" + Thread.currentThread().getId()); + } + EglHelper.throwEglException("eglDestroyContex", egl.eglGetError()); + } + } + } + + /** + * An interface for customizing the eglCreateWindowSurface and eglDestroySurface calls. + *

+ * This interface must be implemented by clients wishing to call + * {@link GLTextureView#setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory)} + */ + public interface EGLWindowSurfaceFactory { + /** + * @return null if the surface cannot be constructed. + */ + EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display, EGLConfig config, + Object nativeWindow); + + void destroySurface(EGL10 egl, EGLDisplay display, EGLSurface surface); + } + + private static class DefaultWindowSurfaceFactory implements EGLWindowSurfaceFactory { + + public EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display, EGLConfig config, + Object nativeWindow) { + EGLSurface result = null; + try { + result = egl.eglCreateWindowSurface(display, config, nativeWindow, null); + } catch (IllegalArgumentException e) { + // This exception indicates that the surface flinger surface + // is not valid. This can happen if the surface flinger surface has + // been torn down, but the application has not yet been + // notified via SurfaceHolder.Callback.surfaceDestroyed. + // In theory the application should be notified first, + // but in practice sometimes it is not. See b/4588890 + Log.e(TAG, "eglCreateWindowSurface", e); + } + return result; + } + + public void destroySurface(EGL10 egl, EGLDisplay display, EGLSurface surface) { + egl.eglDestroySurface(display, surface); + } + } + + /** + * An interface for choosing an EGLConfig configuration from a list of + * potential configurations. + *

+ * This interface must be implemented by clients wishing to call + * {@link GLTextureView#setEGLConfigChooser(EGLConfigChooser)} + */ + public interface EGLConfigChooser { + /** + * Choose a configuration from the list. Implementors typically + * implement this method by calling + * {@link EGL10#eglChooseConfig} and iterating through the results. Please consult the + * EGL specification available from The Khronos Group to learn how to call eglChooseConfig. + * + * @param egl the EGL10 for the current display. + * @param display the current display. + * @return the chosen configuration. + */ + EGLConfig chooseConfig(EGL10 egl, EGLDisplay display); + } + + private abstract class BaseConfigChooser implements EGLConfigChooser { + public BaseConfigChooser(int[] configSpec) { + mConfigSpec = filterConfigSpec(configSpec); + } + + public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) { + int[] num_config = new int[1]; + if (!egl.eglChooseConfig(display, mConfigSpec, null, 0, num_config)) { + throw new IllegalArgumentException("eglChooseConfig failed"); + } + + int numConfigs = num_config[0]; + + if (numConfigs <= 0) { + throw new IllegalArgumentException("No configs match configSpec"); + } + + EGLConfig[] configs = new EGLConfig[numConfigs]; + if (!egl.eglChooseConfig(display, mConfigSpec, configs, numConfigs, num_config)) { + throw new IllegalArgumentException("eglChooseConfig#2 failed"); + } + EGLConfig config = chooseConfig(egl, display, configs); + if (config == null) { + throw new IllegalArgumentException("No config chosen"); + } + return config; + } + + abstract EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, EGLConfig[] configs); + + protected int[] mConfigSpec; + + private int[] filterConfigSpec(int[] configSpec) { + if (eglContextClientVersion != 2) { + return configSpec; + } + /* We know none of the subclasses define EGL_RENDERABLE_TYPE. + * And we know the configSpec is well formed. + */ + int len = configSpec.length; + int[] newConfigSpec = new int[len + 2]; + System.arraycopy(configSpec, 0, newConfigSpec, 0, len - 1); + newConfigSpec[len - 1] = EGL10.EGL_RENDERABLE_TYPE; + newConfigSpec[len] = 0x0004; /* EGL_OPENGL_ES2_BIT */ + newConfigSpec[len + 1] = EGL10.EGL_NONE; + return newConfigSpec; + } + } + + /** + * Choose a configuration with exactly the specified r,g,b,a sizes, + * and at least the specified depth and stencil sizes. + */ + private class ComponentSizeChooser extends BaseConfigChooser { + public ComponentSizeChooser(int redSize, int greenSize, int blueSize, int alphaSize, + int depthSize, int stencilSize) { + super(new int[]{ + EGL10.EGL_RED_SIZE, redSize, EGL10.EGL_GREEN_SIZE, greenSize, EGL10.EGL_BLUE_SIZE, + blueSize, EGL10.EGL_ALPHA_SIZE, alphaSize, EGL10.EGL_DEPTH_SIZE, depthSize, + EGL10.EGL_STENCIL_SIZE, stencilSize, EGL10.EGL_NONE + }); + value = new int[1]; + this.redSize = redSize; + this.greenSize = greenSize; + this.blueSize = blueSize; + this.alphaSize = alphaSize; + this.depthSize = depthSize; + this.stencilSize = stencilSize; + } + + @Override + public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, EGLConfig[] configs) { + for (EGLConfig config : configs) { + int d = findConfigAttrib(egl, display, config, EGL10.EGL_DEPTH_SIZE, 0); + int s = findConfigAttrib(egl, display, config, EGL10.EGL_STENCIL_SIZE, 0); + if ((d >= depthSize) && (s >= stencilSize)) { + int r = findConfigAttrib(egl, display, config, EGL10.EGL_RED_SIZE, 0); + int g = findConfigAttrib(egl, display, config, EGL10.EGL_GREEN_SIZE, 0); + int b = findConfigAttrib(egl, display, config, EGL10.EGL_BLUE_SIZE, 0); + int a = findConfigAttrib(egl, display, config, EGL10.EGL_ALPHA_SIZE, 0); + if ((r == redSize) && (g == greenSize) && (b == blueSize) && (a == alphaSize)) { + return config; + } + } + } + return null; + } + + private int findConfigAttrib(EGL10 egl, EGLDisplay display, EGLConfig config, int attribute, + int defaultValue) { + + if (egl.eglGetConfigAttrib(display, config, attribute, value)) { + return value[0]; + } + return defaultValue; + } + + private int[] value; + // Subclasses can adjust these values: + protected int redSize; + protected int greenSize; + protected int blueSize; + protected int alphaSize; + protected int depthSize; + protected int stencilSize; + } + + /** + * This class will choose a RGB_888 surface with + * or without a depth buffer. + */ + private class SimpleEGLConfigChooser extends ComponentSizeChooser { + public SimpleEGLConfigChooser(boolean withDepthBuffer) { + super(8, 8, 8, 0, withDepthBuffer ? 16 : 0, 0); + } + } + + /** + * An EGL helper class. + */ + + private static class EglHelper { + public EglHelper(WeakReference glTextureViewWeakReference) { + this.glTextureViewWeakRef = glTextureViewWeakReference; + } + + /** + * Initialize EGL for a given configuration spec. + */ + public void start() { + if (LOG_EGL) { + Log.w("EglHelper", "start() tid=" + Thread.currentThread().getId()); + } + /* + * Get an EGL instance + */ + egl = (EGL10) EGLContext.getEGL(); + + /* + * Get to the default display. + */ + eglDisplay = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); + + if (eglDisplay == EGL10.EGL_NO_DISPLAY) { + throw new RuntimeException("eglGetDisplay failed"); + } + + /* + * We can now initialize EGL for that display + */ + int[] version = new int[2]; + if (!egl.eglInitialize(eglDisplay, version)) { + throw new RuntimeException("eglInitialize failed"); + } + GLTextureView view = glTextureViewWeakRef.get(); + if (view == null) { + eglConfig = null; + eglContext = null; + } else { + eglConfig = view.eglConfigChooser.chooseConfig(egl, eglDisplay); + + /* + * Create an EGL context. We want to do this as rarely as we can, because an + * EGL context is a somewhat heavy object. + */ + eglContext = view.eglContextFactory.createContext(egl, eglDisplay, eglConfig); + } + if (eglContext == null || eglContext == EGL10.EGL_NO_CONTEXT) { + eglContext = null; + throwEglException("createContext"); + } + if (LOG_EGL) { + Log.w("EglHelper", + "createContext " + eglContext + " tid=" + Thread.currentThread().getId()); + } + + eglSurface = null; + } + + /** + * Create an egl surface for the current SurfaceHolder surface. If a surface + * already exists, destroy it before creating the new surface. + * + * @return true if the surface was created successfully. + */ + public boolean createSurface() { + if (LOG_EGL) { + Log.w("EglHelper", "createSurface() tid=" + Thread.currentThread().getId()); + } + /* + * Check preconditions. + */ + if (egl == null) { + throw new RuntimeException("egl not initialized"); + } + if (eglDisplay == null) { + throw new RuntimeException("eglDisplay not initialized"); + } + if (eglConfig == null) { + throw new RuntimeException("eglConfig not initialized"); + } + + /* + * The window size has changed, so we need to create a new + * surface. + */ + destroySurfaceImp(); + + /* + * Create an EGL surface we can render into. + */ + GLTextureView view = glTextureViewWeakRef.get(); + if (view != null) { + eglSurface = view.eglWindowSurfaceFactory.createWindowSurface(egl, eglDisplay, eglConfig, + view.getSurfaceTexture()); + } else { + eglSurface = null; + } + + if (eglSurface == null || eglSurface == EGL10.EGL_NO_SURFACE) { + int error = egl.eglGetError(); + if (error == EGL10.EGL_BAD_NATIVE_WINDOW) { + Log.e("EglHelper", "createWindowSurface returned EGL_BAD_NATIVE_WINDOW."); + } + return false; + } + + /* + * Before we can issue GL commands, we need to make sure + * the context is current and bound to a surface. + */ + if (!egl.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext)) { + /* + * Could not make the context current, probably because the underlying + * TextureView surface has been destroyed. + */ + logEglErrorAsWarning("EGLHelper", "eglMakeCurrent", egl.eglGetError()); + return false; + } + + return true; + } + + /** + * Create a GL object for the current EGL context. + */ + GL createGL() { + + GL gl = eglContext.getGL(); + GLTextureView view = glTextureViewWeakRef.get(); + if (view != null) { + if (view.glWrapper != null) { + gl = view.glWrapper.wrap(gl); + } + + if ((view.debugFlags & (DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS)) != 0) { + int configFlags = 0; + Writer log = null; + if ((view.debugFlags & DEBUG_CHECK_GL_ERROR) != 0) { + configFlags |= GLDebugHelper.CONFIG_CHECK_GL_ERROR; + } + if ((view.debugFlags & DEBUG_LOG_GL_CALLS) != 0) { + log = new LogWriter(); + } + gl = GLDebugHelper.wrap(gl, configFlags, log); + } + } + return gl; + } + + /** + * Display the current render surface. + * + * @return the EGL error code from eglSwapBuffers. + */ + public int swap() { + if (!egl.eglSwapBuffers(eglDisplay, eglSurface)) { + return egl.eglGetError(); + } + return EGL10.EGL_SUCCESS; + } + + public void destroySurface() { + if (LOG_EGL) { + Log.w("EglHelper", "destroySurface() tid=" + Thread.currentThread().getId()); + } + destroySurfaceImp(); + } + + private void destroySurfaceImp() { + if (eglSurface != null && eglSurface != EGL10.EGL_NO_SURFACE) { + egl.eglMakeCurrent(eglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, + EGL10.EGL_NO_CONTEXT); + GLTextureView view = glTextureViewWeakRef.get(); + if (view != null) { + view.eglWindowSurfaceFactory.destroySurface(egl, eglDisplay, eglSurface); + } + eglSurface = null; + } + } + + public void finish() { + if (LOG_EGL) { + Log.w("EglHelper", "finish() tid=" + Thread.currentThread().getId()); + } + if (eglContext != null) { + GLTextureView view = glTextureViewWeakRef.get(); + if (view != null) { + view.eglContextFactory.destroyContext(egl, eglDisplay, eglContext); + } + eglContext = null; + } + if (eglDisplay != null) { + egl.eglTerminate(eglDisplay); + eglDisplay = null; + } + } + + private void throwEglException(String function) { + throwEglException(function, egl.eglGetError()); + } + + public static void throwEglException(String function, int error) { + String message = formatEglError(function, error); + if (LOG_THREADS) { + Log.e("EglHelper", + "throwEglException tid=" + Thread.currentThread().getId() + " " + message); + } + throw new RuntimeException(message); + } + + public static void logEglErrorAsWarning(String tag, String function, int error) { + Log.w(tag, formatEglError(function, error)); + } + + public static String formatEglError(String function, int error) { + return function + " failed: " + error; + } + + private WeakReference glTextureViewWeakRef; + EGL10 egl; + EGLDisplay eglDisplay; + EGLSurface eglSurface; + EGLConfig eglConfig; + EGLContext eglContext; + } + + /** + * A generic GL Thread. Takes care of initializing EGL and GL. Delegates + * to a Renderer instance to do the actual drawing. Can be configured to + * render continuously or on request. + *

+ * All potentially blocking synchronization is done through the + * glThreadManager object. This avoids multiple-lock ordering issues. + */ + static class GLThread extends Thread { + GLThread(WeakReference glTextureViewWeakRef) { + super(); + width = 0; + height = 0; + requestRender = true; + renderMode = RENDERMODE_CONTINUOUSLY; + this.glTextureViewWeakRef = glTextureViewWeakRef; + } + + @Override + public void run() { + setName("GLThread " + getId()); + if (LOG_THREADS) { + Log.i("GLThread", "starting tid=" + getId()); + } + + try { + guardedRun(); + } catch (InterruptedException e) { + // fall thru and exit normally + } finally { + glThreadManager.threadExiting(this); + } + } + + /* + * This private method should only be called inside a + * synchronized(glThreadManager) block. + */ + private void stopEglSurfaceLocked() { + if (haveEglSurface) { + haveEglSurface = false; + eglHelper.destroySurface(); + } + } + + /* + * This private method should only be called inside a + * synchronized(glThreadManager) block. + */ + private void stopEglContextLocked() { + if (haveEglContext) { + eglHelper.finish(); + haveEglContext = false; + glThreadManager.releaseEglContextLocked(this); + } + } + + private void guardedRun() throws InterruptedException { + eglHelper = new EglHelper(glTextureViewWeakRef); + haveEglContext = false; + haveEglSurface = false; + try { + GL10 gl = null; + boolean createEglContext = false; + boolean createEglSurface = false; + boolean createGlInterface = false; + boolean lostEglContext = false; + boolean sizeChanged = false; + boolean wantRenderNotification = false; + boolean doRenderNotification = false; + boolean askedToReleaseEglContext = false; + int w = 0; + int h = 0; + Runnable event = null; + + while (true) { + synchronized (glThreadManager) { + while (true) { + if (shouldExit) { + return; + } + + if (!eventQueue.isEmpty()) { + event = eventQueue.remove(0); + break; + } + + // Update the pause state. + boolean pausing = false; + if (paused != requestPaused) { + pausing = requestPaused; + paused = requestPaused; + glThreadManager.notifyAll(); + if (LOG_PAUSE_RESUME) { + Log.i("GLThread", "paused is now " + paused + " tid=" + getId()); + } + } + + // Do we need to give up the EGL context? + if (shouldReleaseEglContext) { + if (LOG_SURFACE) { + Log.i("GLThread", "releasing EGL context because asked to tid=" + getId()); + } + stopEglSurfaceLocked(); + stopEglContextLocked(); + shouldReleaseEglContext = false; + askedToReleaseEglContext = true; + } + + // Have we lost the EGL context? + if (lostEglContext) { + stopEglSurfaceLocked(); + stopEglContextLocked(); + lostEglContext = false; + } + + // When pausing, release the EGL surface: + if (pausing && haveEglSurface) { + if (LOG_SURFACE) { + Log.i("GLThread", "releasing EGL surface because paused tid=" + getId()); + } + stopEglSurfaceLocked(); + } + + // When pausing, optionally release the EGL Context: + if (pausing && haveEglContext) { + GLTextureView view = glTextureViewWeakRef.get(); + boolean preserveEglContextOnPause = + view == null ? false : view.preserveEGLContextOnPause; + if (!preserveEglContextOnPause + || glThreadManager.shouldReleaseEGLContextWhenPausing()) { + stopEglContextLocked(); + if (LOG_SURFACE) { + Log.i("GLThread", "releasing EGL context because paused tid=" + getId()); + } + } + } + + // When pausing, optionally terminate EGL: + if (pausing) { + if (glThreadManager.shouldTerminateEGLWhenPausing()) { + eglHelper.finish(); + if (LOG_SURFACE) { + Log.i("GLThread", "terminating EGL because paused tid=" + getId()); + } + } + } + + // Have we lost the TextureView surface? + if ((!hasSurface) && (!waitingForSurface)) { + if (LOG_SURFACE) { + Log.i("GLThread", "noticed textureView surface lost tid=" + getId()); + } + if (haveEglSurface) { + stopEglSurfaceLocked(); + } + waitingForSurface = true; + surfaceIsBad = false; + glThreadManager.notifyAll(); + } + + // Have we acquired the surface view surface? + if (hasSurface && waitingForSurface) { + if (LOG_SURFACE) { + Log.i("GLThread", "noticed textureView surface acquired tid=" + getId()); + } + waitingForSurface = false; + glThreadManager.notifyAll(); + } + + if (doRenderNotification) { + if (LOG_SURFACE) { + Log.i("GLThread", "sending render notification tid=" + getId()); + } + wantRenderNotification = false; + doRenderNotification = false; + renderComplete = true; + glThreadManager.notifyAll(); + } + + // Ready to draw? + if (readyToDraw()) { + + // If we don't have an EGL context, try to acquire one. + if (!haveEglContext) { + if (askedToReleaseEglContext) { + askedToReleaseEglContext = false; + } else if (glThreadManager.tryAcquireEglContextLocked(this)) { + try { + eglHelper.start(); + } catch (RuntimeException t) { + glThreadManager.releaseEglContextLocked(this); + throw t; + } + haveEglContext = true; + createEglContext = true; + + glThreadManager.notifyAll(); + } + } + + if (haveEglContext && !haveEglSurface) { + haveEglSurface = true; + createEglSurface = true; + createGlInterface = true; + sizeChanged = true; + } + + if (haveEglSurface) { + if (this.sizeChanged) { + sizeChanged = true; + w = width; + h = height; + wantRenderNotification = true; + if (LOG_SURFACE) { + Log.i("GLThread", "noticing that we want render notification tid=" + getId()); + } + + // Destroy and recreate the EGL surface. + createEglSurface = true; + + this.sizeChanged = false; + } + requestRender = false; + glThreadManager.notifyAll(); + break; + } + } + + // By design, this is the only place in a GLThread thread where we wait(). + if (LOG_THREADS) { + Log.i("GLThread", "waiting tid=" + getId() + " haveEglContext: " + haveEglContext + + " haveEglSurface: " + haveEglSurface + " paused: " + paused + " hasSurface: " + + hasSurface + " surfaceIsBad: " + surfaceIsBad + " waitingForSurface: " + + waitingForSurface + " width: " + width + " height: " + height + + " requestRender: " + requestRender + " renderMode: " + renderMode); + } + glThreadManager.wait(); + } + } // end of synchronized(glThreadManager) + + if (event != null) { + event.run(); + event = null; + continue; + } + + if (createEglSurface) { + if (LOG_SURFACE) { + Log.w("GLThread", "egl createSurface"); + } + if (!eglHelper.createSurface()) { + synchronized (glThreadManager) { + surfaceIsBad = true; + glThreadManager.notifyAll(); + } + continue; + } + createEglSurface = false; + } + + if (createGlInterface) { + gl = (GL10) eglHelper.createGL(); + + glThreadManager.checkGLDriver(gl); + createGlInterface = false; + } + + if (createEglContext) { + if (LOG_RENDERER) { + Log.w("GLThread", "onSurfaceCreated"); + } + GLTextureView view = glTextureViewWeakRef.get(); + if (view != null) { + view.renderer.onSurfaceCreated(gl, eglHelper.eglConfig); + } + createEglContext = false; + } + + if (sizeChanged) { + if (LOG_RENDERER) { + Log.w("GLThread", "onSurfaceChanged(" + w + ", " + h + ")"); + } + GLTextureView view = glTextureViewWeakRef.get(); + if (view != null) { + view.renderer.onSurfaceChanged(gl, w, h); + } + sizeChanged = false; + } + + if (LOG_RENDERER_DRAW_FRAME) { + Log.w("GLThread", "onDrawFrame tid=" + getId()); + } + { + GLTextureView view = glTextureViewWeakRef.get(); + if (view != null) { + view.renderer.onDrawFrame(gl); + } + } + int swapError = eglHelper.swap(); + switch (swapError) { + case EGL10.EGL_SUCCESS: + break; + case EGL11.EGL_CONTEXT_LOST: + if (LOG_SURFACE) { + Log.i("GLThread", "egl context lost tid=" + getId()); + } + lostEglContext = true; + break; + default: + // Other errors typically mean that the current surface is bad, + // probably because the TextureView surface has been destroyed, + // but we haven't been notified yet. + // Log the error to help developers understand why rendering stopped. + EglHelper.logEglErrorAsWarning("GLThread", "eglSwapBuffers", swapError); + + synchronized (glThreadManager) { + surfaceIsBad = true; + glThreadManager.notifyAll(); + } + break; + } + + if (wantRenderNotification) { + doRenderNotification = true; + } + } + } finally { + /* + * clean-up everything... + */ + synchronized (glThreadManager) { + stopEglSurfaceLocked(); + stopEglContextLocked(); + } + } + } + + public boolean ableToDraw() { + return haveEglContext && haveEglSurface && readyToDraw(); + } + + private boolean readyToDraw() { + return (!paused) && hasSurface && (!surfaceIsBad) && (width > 0) && (height > 0) && ( + requestRender || (renderMode == RENDERMODE_CONTINUOUSLY)); + } + + public void setRenderMode(int renderMode) { + if (!((RENDERMODE_WHEN_DIRTY <= renderMode) && (renderMode <= RENDERMODE_CONTINUOUSLY))) { + throw new IllegalArgumentException("renderMode"); + } + synchronized (glThreadManager) { + this.renderMode = renderMode; + glThreadManager.notifyAll(); + } + } + + public int getRenderMode() { + synchronized (glThreadManager) { + return renderMode; + } + } + + public void requestRender() { + synchronized (glThreadManager) { + requestRender = true; + glThreadManager.notifyAll(); + } + } + + public void surfaceCreated() { + synchronized (glThreadManager) { + if (LOG_THREADS) { + Log.i("GLThread", "surfaceCreated tid=" + getId()); + } + hasSurface = true; + glThreadManager.notifyAll(); + while ((waitingForSurface) && (!exited)) { + try { + glThreadManager.wait(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + } + } + + public void surfaceDestroyed() { + synchronized (glThreadManager) { + if (LOG_THREADS) { + Log.i("GLThread", "surfaceDestroyed tid=" + getId()); + } + hasSurface = false; + glThreadManager.notifyAll(); + while ((!waitingForSurface) && (!exited)) { + try { + glThreadManager.wait(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + } + } + + public void onPause() { + synchronized (glThreadManager) { + if (LOG_PAUSE_RESUME) { + Log.i("GLThread", "onPause tid=" + getId()); + } + requestPaused = true; + glThreadManager.notifyAll(); + while ((!exited) && (!paused)) { + if (LOG_PAUSE_RESUME) { + Log.i("Main thread", "onPause waiting for paused."); + } + try { + glThreadManager.wait(); + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + } + } + } + } + + public void onResume() { + synchronized (glThreadManager) { + if (LOG_PAUSE_RESUME) { + Log.i("GLThread", "onResume tid=" + getId()); + } + requestPaused = false; + requestRender = true; + renderComplete = false; + glThreadManager.notifyAll(); + while ((!exited) && paused && (!renderComplete)) { + if (LOG_PAUSE_RESUME) { + Log.i("Main thread", "onResume waiting for !paused."); + } + try { + glThreadManager.wait(); + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + } + } + } + } + + public void onWindowResize(int w, int h) { + synchronized (glThreadManager) { + width = w; + height = h; + sizeChanged = true; + requestRender = true; + renderComplete = false; + glThreadManager.notifyAll(); + + // Wait for thread to react to resize and render a frame + while (!exited && !paused && !renderComplete && ableToDraw()) { + if (LOG_SURFACE) { + Log.i("Main thread", "onWindowResize waiting for render complete from tid=" + getId()); + } + try { + glThreadManager.wait(); + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + } + } + } + } + + public void requestExitAndWait() { + // don't call this from GLThread thread or it is a guaranteed + // deadlock! + synchronized (glThreadManager) { + shouldExit = true; + glThreadManager.notifyAll(); + while (!exited) { + try { + glThreadManager.wait(); + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + } + } + } + } + + public void requestReleaseEglContextLocked() { + shouldReleaseEglContext = true; + glThreadManager.notifyAll(); + } + + /** + * Queue an "event" to be run on the GL rendering thread. + * + * @param r the runnable to be run on the GL rendering thread. + */ + public void queueEvent(Runnable r) { + if (r == null) { + throw new IllegalArgumentException("r must not be null"); + } + synchronized (glThreadManager) { + eventQueue.add(r); + glThreadManager.notifyAll(); + } + } + + // Once the thread is started, all accesses to the following member + // variables are protected by the glThreadManager monitor + private boolean shouldExit; + private boolean exited; + private boolean requestPaused; + private boolean paused; + private boolean hasSurface; + private boolean surfaceIsBad; + private boolean waitingForSurface; + private boolean haveEglContext; + private boolean haveEglSurface; + private boolean shouldReleaseEglContext; + private int width; + private int height; + private int renderMode; + private boolean requestRender; + private boolean renderComplete; + private ArrayList eventQueue = new ArrayList<>(); + private boolean sizeChanged = true; + + // End of member variables protected by the glThreadManager monitor. + + private EglHelper eglHelper; + + /** + * Set once at thread construction time, nulled out when the parent view is garbage + * called. This weak reference allows the GLTextureView to be garbage collected while + * the GLThread is still alive. + */ + private WeakReference glTextureViewWeakRef; + } + + static class LogWriter extends Writer { + + @Override + public void close() { + flushBuilder(); + } + + @Override + public void flush() { + flushBuilder(); + } + + @Override + public void write(char[] buf, int offset, int count) { + for (int i = 0; i < count; i++) { + char c = buf[offset + i]; + if (c == '\n') { + flushBuilder(); + } else { + builder.append(c); + } + } + } + + private void flushBuilder() { + if (builder.length() > 0) { + Log.v("GLTextureView", builder.toString()); + builder.delete(0, builder.length()); + } + } + + private StringBuilder builder = new StringBuilder(); + } + + private void checkRenderThreadState() { + if (glThread != null) { + throw new IllegalStateException("setRenderer has already been called for this instance."); + } + } + + private static class GLThreadManager { + private static String TAG = "GLThreadManager"; + + public synchronized void threadExiting(GLThread thread) { + if (LOG_THREADS) { + Log.i("GLThread", "exiting tid=" + thread.getId()); + } + thread.exited = true; + if (eglOwner == thread) { + eglOwner = null; + } + notifyAll(); + } + + /* + * Tries once to acquire the right to use an EGL + * context. Does not block. Requires that we are already + * in the glThreadManager monitor when this is called. + * + * @return true if the right to use an EGL context was acquired. + */ + public boolean tryAcquireEglContextLocked(GLThread thread) { + if (eglOwner == thread || eglOwner == null) { + eglOwner = thread; + notifyAll(); + return true; + } + checkGLESVersion(); + if (multipleGLESContextsAllowed) { + return true; + } + // Notify the owning thread that it should release the context. + // TODO: implement a fairness policy. Currently + // if the owning thread is drawing continuously it will just + // reacquire the EGL context. + if (eglOwner != null) { + eglOwner.requestReleaseEglContextLocked(); + } + return false; + } + + /* + * Releases the EGL context. Requires that we are already in the + * glThreadManager monitor when this is called. + */ + public void releaseEglContextLocked(GLThread thread) { + if (eglOwner == thread) { + eglOwner = null; + } + notifyAll(); + } + + public synchronized boolean shouldReleaseEGLContextWhenPausing() { + // Release the EGL context when pausing even if + // the hardware supports multiple EGL contexts. + // Otherwise the device could run out of EGL contexts. + return limitedGLESContexts; + } + + public synchronized boolean shouldTerminateEGLWhenPausing() { + checkGLESVersion(); + return !multipleGLESContextsAllowed; + } + + public synchronized void checkGLDriver(GL10 gl) { + if (!glesDriverCheckComplete) { + checkGLESVersion(); + String renderer = gl.glGetString(GL10.GL_RENDERER); + if (glesVersion < kGLES_20) { + multipleGLESContextsAllowed = !renderer.startsWith(kMSM7K_RENDERER_PREFIX); + notifyAll(); + } + limitedGLESContexts = !multipleGLESContextsAllowed; + if (LOG_SURFACE) { + Log.w(TAG, "checkGLDriver renderer = \"" + renderer + "\" multipleContextsAllowed = " + + multipleGLESContextsAllowed + " limitedGLESContexts = " + limitedGLESContexts); + } + glesDriverCheckComplete = true; + } + } + + private void checkGLESVersion() { + if (!glesVersionCheckComplete) { + glesVersionCheckComplete = true; + } + } + + /** + * This check was required for some pre-Android-3.0 hardware. Android 3.0 provides + * support for hardware-accelerated views, therefore multiple EGL contexts are + * supported on all Android 3.0+ EGL drivers. + */ + private boolean glesVersionCheckComplete; + private int glesVersion; + private boolean glesDriverCheckComplete; + private boolean multipleGLESContextsAllowed; + private boolean limitedGLESContexts; + private static final int kGLES_20 = 0x20000; + private static final String kMSM7K_RENDERER_PREFIX = "Q3Dimension MSM7500 "; + private GLThread eglOwner; + } + + private static final GLThreadManager glThreadManager = new GLThreadManager(); + + private final WeakReference mThisWeakRef = new WeakReference<>(this); + private GLThread glThread; + private Renderer renderer; + private boolean detached; + private EGLConfigChooser eglConfigChooser; + private EGLContextFactory eglContextFactory; + private EGLWindowSurfaceFactory eglWindowSurfaceFactory; + private GLWrapper glWrapper; + private int debugFlags; + private int eglContextClientVersion; + private boolean preserveEGLContextOnPause; + private List surfaceTextureListeners = new ArrayList<>(); +} diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImage.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/GPUImage.java similarity index 62% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImage.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/GPUImage.java index 8392a5a9a..4b3dcadba 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImage.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/GPUImage.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,6 @@ package jp.co.cyberagent.android.gpuimage; -import android.annotation.TargetApi; import android.app.ActivityManager; import android.content.Context; import android.content.pm.ConfigurationInfo; @@ -32,29 +31,43 @@ import android.net.Uri; import android.opengl.GLSurfaceView; import android.os.AsyncTask; -import android.os.Build; import android.os.Environment; import android.os.Handler; import android.provider.MediaStore; import android.view.Display; import android.view.WindowManager; -import java.io.*; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; import java.net.URL; import java.util.List; -import java.util.concurrent.Semaphore; + +import jp.co.cyberagent.android.gpuimage.filter.GPUImageFilter; +import jp.co.cyberagent.android.gpuimage.util.Rotation; /** * The main accessor for GPUImage functionality. This class helps to do common * tasks through a simple interface. */ public class GPUImage { - private final Context mContext; - private final GPUImageRenderer mRenderer; - private GLSurfaceView mGlSurfaceView; - private GPUImageFilter mFilter; - private Bitmap mCurrentBitmap; - private ScaleType mScaleType = ScaleType.CENTER_CROP; + + public enum ScaleType {CENTER_INSIDE, CENTER_CROP} + + static final int SURFACE_TYPE_SURFACE_VIEW = 0; + static final int SURFACE_TYPE_TEXTURE_VIEW = 1; + + private final Context context; + private final GPUImageRenderer renderer; + private int surfaceType = SURFACE_TYPE_SURFACE_VIEW; + private GLSurfaceView glSurfaceView; + private GLTextureView glTextureView; + private GPUImageFilter filter; + private Bitmap currentBitmap; + private ScaleType scaleType = ScaleType.CENTER_CROP; + private int scaleWidth, scaleHeight; /** * Instantiates a new GPUImage object. @@ -66,9 +79,9 @@ public GPUImage(final Context context) { throw new IllegalStateException("OpenGL ES 2.0 is not supported on this phone."); } - mContext = context; - mFilter = new GPUImageFilter(); - mRenderer = new GPUImageRenderer(mFilter); + this.context = context; + filter = new GPUImageFilter(); + renderer = new GPUImageRenderer(filter); } /** @@ -91,61 +104,91 @@ private boolean supportsOpenGLES2(final Context context) { * @param view the GLSurfaceView */ public void setGLSurfaceView(final GLSurfaceView view) { - mGlSurfaceView = view; - mGlSurfaceView.setEGLContextClientVersion(2); - mGlSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0); - mGlSurfaceView.getHolder().setFormat(PixelFormat.RGBA_8888); - mGlSurfaceView.setRenderer(mRenderer); - mGlSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); - mGlSurfaceView.requestRender(); + surfaceType = SURFACE_TYPE_SURFACE_VIEW; + glSurfaceView = view; + glSurfaceView.setEGLContextClientVersion(2); + glSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0); + glSurfaceView.getHolder().setFormat(PixelFormat.RGBA_8888); + glSurfaceView.setRenderer(renderer); + glSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); + glSurfaceView.requestRender(); + } + + /** + * Sets the GLTextureView which will display the preview. + * + * @param view the GLTextureView + */ + public void setGLTextureView(final GLTextureView view) { + surfaceType = SURFACE_TYPE_TEXTURE_VIEW; + glTextureView = view; + glTextureView.setEGLContextClientVersion(2); + glTextureView.setEGLConfigChooser(8, 8, 8, 8, 16, 0); + glTextureView.setOpaque(false); + glTextureView.setRenderer(renderer); + glTextureView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); + glTextureView.requestRender(); } /** * Sets the background color * - * @param red red color value + * @param red red color value * @param green green color value - * @param blue red color value + * @param blue red color value */ public void setBackgroundColor(float red, float green, float blue) { - mRenderer.setBackgroundColor(red, green, blue); + renderer.setBackgroundColor(red, green, blue); } /** * Request the preview to be rendered again. */ public void requestRender() { - if (mGlSurfaceView != null) { - mGlSurfaceView.requestRender(); + if (surfaceType == SURFACE_TYPE_SURFACE_VIEW) { + if (glSurfaceView != null) { + glSurfaceView.requestRender(); + } + } else if (surfaceType == SURFACE_TYPE_TEXTURE_VIEW) { + if (glTextureView != null) { + glTextureView.requestRender(); + } } } /** + * Deprecated: Please call + * {@link GPUImage#updatePreviewFrame(byte[], int, int)} frame by frame + *

* Sets the up camera to be connected to GPUImage to get a filtered preview. * * @param camera the camera */ + @Deprecated public void setUpCamera(final Camera camera) { setUpCamera(camera, 0, false, false); } /** + * Deprecated: Please call + * {@link GPUImage#updatePreviewFrame(byte[], int, int)} frame by frame + *

* Sets the up camera to be connected to GPUImage to get a filtered preview. * - * @param camera the camera - * @param degrees by how many degrees the image should be rotated + * @param camera the camera + * @param degrees by how many degrees the image should be rotated * @param flipHorizontal if the image should be flipped horizontally - * @param flipVertical if the image should be flipped vertically + * @param flipVertical if the image should be flipped vertically */ + @Deprecated public void setUpCamera(final Camera camera, final int degrees, final boolean flipHorizontal, - final boolean flipVertical) { - mGlSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY); - if (Build.VERSION.SDK_INT > Build.VERSION_CODES.GINGERBREAD_MR1) { - setUpCameraGingerbread(camera); - } else { - camera.setPreviewCallback(mRenderer); - camera.startPreview(); + final boolean flipVertical) { + if (surfaceType == SURFACE_TYPE_SURFACE_VIEW) { + glSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY); + } else if (surfaceType == SURFACE_TYPE_TEXTURE_VIEW) { + glTextureView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY); } + renderer.setUpSurfaceTexture(camera); Rotation rotation = Rotation.NORMAL; switch (degrees) { case 90: @@ -158,12 +201,7 @@ public void setUpCamera(final Camera camera, final int degrees, final boolean fl rotation = Rotation.ROTATION_270; break; } - mRenderer.setRotationCamera(rotation, flipHorizontal, flipVertical); - } - - @TargetApi(11) - private void setUpCameraGingerbread(final Camera camera) { - mRenderer.setUpSurfaceTexture(camera); + renderer.setRotationCamera(rotation, flipHorizontal, flipVertical); } /** @@ -173,8 +211,8 @@ private void setUpCameraGingerbread(final Camera camera) { * @param filter the new filter */ public void setFilter(final GPUImageFilter filter) { - mFilter = filter; - mRenderer.setFilter(mFilter); + this.filter = filter; + renderer.setFilter(this.filter); requestRender(); } @@ -184,11 +222,22 @@ public void setFilter(final GPUImageFilter filter) { * @param bitmap the new image */ public void setImage(final Bitmap bitmap) { - mCurrentBitmap = bitmap; - mRenderer.setImageBitmap(bitmap, false); + currentBitmap = bitmap; + renderer.setImageBitmap(bitmap, false); requestRender(); } + /** + * Update camera preview frame with YUV format data. + * + * @param data Camera preview YUV data for frame. + * @param width width of camera preview + * @param height height of camera preview + */ + public void updatePreviewFrame(final byte[] data, final int width, final int height) { + renderer.onPreviewFrame(data, width, height); + } + /** * This sets the scale type of GPUImage. This has to be run before setting the image. * If image is set and scale type changed, image needs to be reset. @@ -196,20 +245,30 @@ public void setImage(final Bitmap bitmap) { * @param scaleType The new ScaleType */ public void setScaleType(ScaleType scaleType) { - mScaleType = scaleType; - mRenderer.setScaleType(scaleType); - mRenderer.deleteImage(); - mCurrentBitmap = null; + this.scaleType = scaleType; + renderer.setScaleType(scaleType); + renderer.deleteImage(); + currentBitmap = null; requestRender(); } + /** + * This gets the size of the image. This makes it easier to adjust + * the size of your imagePreview to the the size of the scaled image. + * + * @return array with width and height of bitmap image + */ + public int[] getScaleSize() { + return new int[] {scaleWidth, scaleHeight}; + } + /** * Sets the rotation of the displayed image. * * @param rotation new rotation */ public void setRotation(Rotation rotation) { - mRenderer.setRotation(rotation); + renderer.setRotation(rotation); } /** @@ -218,15 +277,15 @@ public void setRotation(Rotation rotation) { * @param rotation new rotation */ public void setRotation(Rotation rotation, boolean flipHorizontal, boolean flipVertical) { - mRenderer.setRotation(rotation, flipHorizontal, flipVertical); + renderer.setRotation(rotation, flipHorizontal, flipVertical); } /** * Deletes the current image. */ public void deleteImage() { - mRenderer.deleteImage(); - mCurrentBitmap = null; + renderer.deleteImage(); + currentBitmap = null; requestRender(); } @@ -252,11 +311,14 @@ private String getPath(final Uri uri) { String[] projection = { MediaStore.Images.Media.DATA, }; - Cursor cursor = mContext.getContentResolver() + Cursor cursor = context.getContentResolver() .query(uri, projection, null, null, null); - int pathIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); String path = null; + if (cursor == null) { + return null; + } if (cursor.moveToFirst()) { + int pathIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); path = cursor.getString(pathIndex); } cursor.close(); @@ -269,7 +331,7 @@ private String getPath(final Uri uri) { * @return the current image with filter applied */ public Bitmap getBitmapWithFilterApplied() { - return getBitmapWithFilterApplied(mCurrentBitmap); + return getBitmapWithFilterApplied(currentBitmap); } /** @@ -279,43 +341,54 @@ public Bitmap getBitmapWithFilterApplied() { * @return the bitmap with filter applied */ public Bitmap getBitmapWithFilterApplied(final Bitmap bitmap) { - if (mGlSurfaceView != null) { - mRenderer.deleteImage(); - mRenderer.runOnDraw(new Runnable() { + return getBitmapWithFilterApplied(bitmap, false); + } + + /** + * Gets the given bitmap with current filter applied as a Bitmap. + * + * @param bitmap the bitmap on which the current filter should be applied + * @param recycle recycle the bitmap or not. + * @return the bitmap with filter applied + */ + public Bitmap getBitmapWithFilterApplied(final Bitmap bitmap, boolean recycle) { + if (glSurfaceView != null || glTextureView != null) { + renderer.deleteImage(); + renderer.runOnDraw(new Runnable() { @Override public void run() { - synchronized(mFilter) { - mFilter.destroy(); - mFilter.notify(); + synchronized (filter) { + filter.destroy(); + filter.notify(); } } }); - synchronized(mFilter) { + synchronized (filter) { requestRender(); try { - mFilter.wait(); + filter.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } - GPUImageRenderer renderer = new GPUImageRenderer(mFilter); + GPUImageRenderer renderer = new GPUImageRenderer(filter); renderer.setRotation(Rotation.NORMAL, - mRenderer.isFlippedHorizontally(), mRenderer.isFlippedVertically()); - renderer.setScaleType(mScaleType); + this.renderer.isFlippedHorizontally(), this.renderer.isFlippedVertically()); + renderer.setScaleType(scaleType); PixelBuffer buffer = new PixelBuffer(bitmap.getWidth(), bitmap.getHeight()); buffer.setRenderer(renderer); - renderer.setImageBitmap(bitmap, false); + renderer.setImageBitmap(bitmap, recycle); Bitmap result = buffer.getBitmap(); - mFilter.destroy(); + filter.destroy(); renderer.deleteImage(); buffer.destroy(); - mRenderer.setFilter(mFilter); - if (mCurrentBitmap != null) { - mRenderer.setImageBitmap(mCurrentBitmap, false); + this.renderer.setFilter(filter); + if (currentBitmap != null) { + this.renderer.setImageBitmap(currentBitmap, false); } requestRender(); @@ -329,12 +402,12 @@ public void run() { * bitmap. The order of the calls to the listener will be the same as the * filter order. * - * @param bitmap the bitmap on which the filters will be applied - * @param filters the filters which will be applied on the bitmap + * @param bitmap the bitmap on which the filters will be applied + * @param filters the filters which will be applied on the bitmap * @param listener the listener on which the results will be notified */ public static void getBitmapForMultipleFilters(final Bitmap bitmap, - final List filters, final ResponseListener listener) { + final List filters, final ResponseListener listener) { if (filters.isEmpty()) { return; } @@ -353,9 +426,6 @@ public static void getBitmapForMultipleFilters(final Bitmap bitmap, } /** - * Deprecated: Please use - * {@link GPUImageView#saveToPictures(String, String, jp.co.cyberagent.android.gpuimage.GPUImageView.OnPictureSavedListener)} - * * Save current image with applied filter to Pictures. It will be stored on * the default Picture folder on the phone below the given folderName and * fileName.
@@ -363,33 +433,28 @@ public static void getBitmapForMultipleFilters(final Bitmap bitmap, * listener. * * @param folderName the folder name - * @param fileName the file name - * @param listener the listener + * @param fileName the file name + * @param listener the listener */ - @Deprecated public void saveToPictures(final String folderName, final String fileName, - final OnPictureSavedListener listener) { - saveToPictures(mCurrentBitmap, folderName, fileName, listener); + final OnPictureSavedListener listener) { + saveToPictures(currentBitmap, folderName, fileName, listener); } /** - * Deprecated: Please use - * {@link GPUImageView#saveToPictures(String, String, jp.co.cyberagent.android.gpuimage.GPUImageView.OnPictureSavedListener)} - * * Apply and save the given bitmap with applied filter to Pictures. It will * be stored on the default Picture folder on the phone below the given * folerName and fileName.
* This method is async and will notify when the image was saved through the * listener. * - * @param bitmap the bitmap + * @param bitmap the bitmap * @param folderName the folder name - * @param fileName the file name - * @param listener the listener + * @param fileName the file name + * @param listener the listener */ - @Deprecated public void saveToPictures(final Bitmap bitmap, final String folderName, final String fileName, - final OnPictureSavedListener listener) { + final OnPictureSavedListener listener) { new SaveTask(bitmap, folderName, fileName, listener).execute(); } @@ -399,30 +464,30 @@ public void saveToPictures(final Bitmap bitmap, final String folderName, final S * @param runnable The runnable to be run on the OpenGL thread. */ void runOnGLThread(Runnable runnable) { - mRenderer.runOnDrawEnd(runnable); + renderer.runOnDrawEnd(runnable); } private int getOutputWidth() { - if (mRenderer != null && mRenderer.getFrameWidth() != 0) { - return mRenderer.getFrameWidth(); - } else if (mCurrentBitmap != null) { - return mCurrentBitmap.getWidth(); + if (renderer != null && renderer.getFrameWidth() != 0) { + return renderer.getFrameWidth(); + } else if (currentBitmap != null) { + return currentBitmap.getWidth(); } else { WindowManager windowManager = - (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); + (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); Display display = windowManager.getDefaultDisplay(); return display.getWidth(); } } private int getOutputHeight() { - if (mRenderer != null && mRenderer.getFrameHeight() != 0) { - return mRenderer.getFrameHeight(); - } else if (mCurrentBitmap != null) { - return mCurrentBitmap.getHeight(); + if (renderer != null && renderer.getFrameHeight() != 0) { + return renderer.getFrameHeight(); + } else if (currentBitmap != null) { + return currentBitmap.getHeight(); } else { WindowManager windowManager = - (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); + (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); Display display = windowManager.getDefaultDisplay(); return display.getHeight(); } @@ -431,48 +496,47 @@ private int getOutputHeight() { @Deprecated private class SaveTask extends AsyncTask { - private final Bitmap mBitmap; - private final String mFolderName; - private final String mFileName; - private final OnPictureSavedListener mListener; - private final Handler mHandler; + private final Bitmap bitmap; + private final String folderName; + private final String fileName; + private final OnPictureSavedListener listener; + private final Handler handler; public SaveTask(final Bitmap bitmap, final String folderName, final String fileName, - final OnPictureSavedListener listener) { - mBitmap = bitmap; - mFolderName = folderName; - mFileName = fileName; - mListener = listener; - mHandler = new Handler(); + final OnPictureSavedListener listener) { + this.bitmap = bitmap; + this.folderName = folderName; + this.fileName = fileName; + this.listener = listener; + handler = new Handler(); } @Override protected Void doInBackground(final Void... params) { - Bitmap result = getBitmapWithFilterApplied(mBitmap); - saveImage(mFolderName, mFileName, result); + Bitmap result = getBitmapWithFilterApplied(bitmap); + saveImage(folderName, fileName, result); return null; } private void saveImage(final String folderName, final String fileName, final Bitmap image) { - File path = Environment - .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); + File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); File file = new File(path, folderName + "/" + fileName); try { file.getParentFile().mkdirs(); image.compress(CompressFormat.JPEG, 80, new FileOutputStream(file)); - MediaScannerConnection.scanFile(mContext, - new String[] { - file.toString() + MediaScannerConnection.scanFile(context, + new String[]{ + file.toString() }, null, new MediaScannerConnection.OnScanCompletedListener() { @Override public void onScanCompleted(final String path, final Uri uri) { - if (mListener != null) { - mHandler.post(new Runnable() { + if (listener != null) { + handler.post(new Runnable() { @Override public void run() { - mListener.onPictureSaved(uri); + listener.onPictureSaved(uri); } }); } @@ -490,21 +554,23 @@ public interface OnPictureSavedListener { private class LoadImageUriTask extends LoadImageTask { - private final Uri mUri; + private final Uri uri; public LoadImageUriTask(GPUImage gpuImage, Uri uri) { super(gpuImage); - mUri = uri; + this.uri = uri; } @Override protected Bitmap decode(BitmapFactory.Options options) { try { InputStream inputStream; - if (mUri.getScheme().startsWith("http") || mUri.getScheme().startsWith("https")) { - inputStream = new URL(mUri.toString()).openStream(); + if (uri.getScheme().startsWith("http") || uri.getScheme().startsWith("https")) { + inputStream = new URL(uri.toString()).openStream(); + } else if (uri.getPath().startsWith("/android_asset/")) { + inputStream = context.getAssets().open(uri.getPath().substring(("/android_asset/").length())); } else { - inputStream = mContext.getContentResolver().openInputStream(mUri); + inputStream = context.getContentResolver().openInputStream(uri); } return BitmapFactory.decodeStream(inputStream, null, options); } catch (Exception e) { @@ -515,8 +581,8 @@ protected Bitmap decode(BitmapFactory.Options options) { @Override protected int getImageOrientation() throws IOException { - Cursor cursor = mContext.getContentResolver().query(mUri, - new String[] { MediaStore.Images.ImageColumns.ORIENTATION }, null, null, null); + Cursor cursor = context.getContentResolver().query(uri, + new String[]{MediaStore.Images.ImageColumns.ORIENTATION}, null, null, null); if (cursor == null || cursor.getCount() != 1) { return 0; @@ -531,21 +597,21 @@ protected int getImageOrientation() throws IOException { private class LoadImageFileTask extends LoadImageTask { - private final File mImageFile; + private final File imageFile; public LoadImageFileTask(GPUImage gpuImage, File file) { super(gpuImage); - mImageFile = file; + imageFile = file; } @Override protected Bitmap decode(BitmapFactory.Options options) { - return BitmapFactory.decodeFile(mImageFile.getAbsolutePath(), options); + return BitmapFactory.decodeFile(imageFile.getAbsolutePath(), options); } @Override protected int getImageOrientation() throws IOException { - ExifInterface exif = new ExifInterface(mImageFile.getAbsolutePath()); + ExifInterface exif = new ExifInterface(imageFile.getAbsolutePath()); int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1); switch (orientation) { case ExifInterface.ORIENTATION_NORMAL: @@ -564,36 +630,35 @@ protected int getImageOrientation() throws IOException { private abstract class LoadImageTask extends AsyncTask { - private final GPUImage mGPUImage; - private int mOutputWidth; - private int mOutputHeight; + private final GPUImage gpuImage; + private int outputWidth; + private int outputHeight; - @SuppressWarnings("deprecation") public LoadImageTask(final GPUImage gpuImage) { - mGPUImage = gpuImage; + this.gpuImage = gpuImage; } @Override protected Bitmap doInBackground(Void... params) { - if (mRenderer != null && mRenderer.getFrameWidth() == 0) { + if (renderer != null && renderer.getFrameWidth() == 0) { try { - synchronized (mRenderer.mSurfaceChangedWaiter) { - mRenderer.mSurfaceChangedWaiter.wait(3000); + synchronized (renderer.surfaceChangedWaiter) { + renderer.surfaceChangedWaiter.wait(3000); } } catch (InterruptedException e) { e.printStackTrace(); } } - mOutputWidth = getOutputWidth(); - mOutputHeight = getOutputHeight(); + outputWidth = getOutputWidth(); + outputHeight = getOutputHeight(); return loadResizedImage(); } @Override protected void onPostExecute(Bitmap bitmap) { super.onPostExecute(bitmap); - mGPUImage.deleteImage(); - mGPUImage.setImage(bitmap); + gpuImage.deleteImage(); + gpuImage.setImage(bitmap); } protected abstract Bitmap decode(BitmapFactory.Options options); @@ -603,7 +668,7 @@ private Bitmap loadResizedImage() { options.inJustDecodeBounds = true; decode(options); int scale = 1; - while (checkSize(options.outWidth / scale > mOutputWidth, options.outHeight / scale > mOutputHeight)) { + while (checkSize(options.outWidth / scale > outputWidth, options.outHeight / scale > outputHeight)) { scale++; } @@ -637,10 +702,10 @@ private Bitmap scaleBitmap(Bitmap bitmap) { System.gc(); } - if (mScaleType == ScaleType.CENTER_CROP) { + if (scaleType == ScaleType.CENTER_CROP) { // Crop it - int diffWidth = newSize[0] - mOutputWidth; - int diffHeight = newSize[1] - mOutputHeight; + int diffWidth = newSize[0] - outputWidth; + int diffHeight = newSize[1] - outputHeight; workBitmap = Bitmap.createBitmap(bitmap, diffWidth / 2, diffHeight / 2, newSize[0] - diffWidth, newSize[1] - diffHeight); if (workBitmap != bitmap) { @@ -662,24 +727,26 @@ private int[] getScaleSize(int width, int height) { float newWidth; float newHeight; - float withRatio = (float) width / mOutputWidth; - float heightRatio = (float) height / mOutputHeight; + float withRatio = (float) width / outputWidth; + float heightRatio = (float) height / outputHeight; - boolean adjustWidth = mScaleType == ScaleType.CENTER_CROP + boolean adjustWidth = scaleType == ScaleType.CENTER_CROP ? withRatio > heightRatio : withRatio < heightRatio; if (adjustWidth) { - newHeight = mOutputHeight; + newHeight = outputHeight; newWidth = (newHeight / height) * width; } else { - newWidth = mOutputWidth; + newWidth = outputWidth; newHeight = (newWidth / width) * height; } + scaleWidth = Math.round(newWidth); + scaleHeight = Math.round(newHeight); return new int[]{Math.round(newWidth), Math.round(newHeight)}; } private boolean checkSize(boolean widthBigger, boolean heightBigger) { - if (mScaleType == ScaleType.CENTER_CROP) { + if (scaleType == ScaleType.CENTER_CROP) { return widthBigger && heightBigger; } else { return widthBigger || heightBigger; @@ -713,5 +780,7 @@ public interface ResponseListener { void response(T item); } - public enum ScaleType { CENTER_INSIDE, CENTER_CROP } + public GPUImageRenderer getRenderer() { + return renderer; + } } diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageNativeLibrary.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/GPUImageNativeLibrary.java similarity index 82% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageNativeLibrary.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/GPUImageNativeLibrary.java index ce8c31b87..0a171c7dd 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageNativeLibrary.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/GPUImageNativeLibrary.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,12 +16,16 @@ package jp.co.cyberagent.android.gpuimage; +import android.graphics.Bitmap; + public class GPUImageNativeLibrary { static { - System.loadLibrary("gpuimage-library"); + System.loadLibrary("yuv-decoder"); } public static native void YUVtoRBGA(byte[] yuv, int width, int height, int[] out); public static native void YUVtoARBG(byte[] yuv, int width, int height, int[] out); + + public static native void adjustBitmap(Bitmap srcBitmap); } diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageRenderer.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/GPUImageRenderer.java similarity index 58% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageRenderer.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/GPUImageRenderer.java index 691550bde..5fea701bb 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageRenderer.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/GPUImageRenderer.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,6 @@ package jp.co.cyberagent.android.gpuimage; -import android.annotation.TargetApi; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.SurfaceTexture; @@ -24,12 +23,8 @@ import android.hardware.Camera.PreviewCallback; import android.hardware.Camera.Size; import android.opengl.GLES20; -import android.opengl.GLSurfaceView.Renderer; +import android.opengl.GLSurfaceView; -import jp.co.cyberagent.android.gpuimage.util.TextureRotationUtil; - -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.opengles.GL10; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -38,56 +33,63 @@ import java.util.LinkedList; import java.util.Queue; +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.opengles.GL10; + +import jp.co.cyberagent.android.gpuimage.filter.GPUImageFilter; +import jp.co.cyberagent.android.gpuimage.util.OpenGlUtils; +import jp.co.cyberagent.android.gpuimage.util.Rotation; +import jp.co.cyberagent.android.gpuimage.util.TextureRotationUtil; + import static jp.co.cyberagent.android.gpuimage.util.TextureRotationUtil.TEXTURE_NO_ROTATION; -@TargetApi(11) -public class GPUImageRenderer implements Renderer, PreviewCallback { - public static final int NO_IMAGE = -1; - static final float CUBE[] = { +public class GPUImageRenderer implements GLSurfaceView.Renderer, GLTextureView.Renderer, PreviewCallback { + private static final int NO_IMAGE = -1; + public static final float CUBE[] = { -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, }; - private GPUImageFilter mFilter; + private GPUImageFilter filter; - public final Object mSurfaceChangedWaiter = new Object(); + public final Object surfaceChangedWaiter = new Object(); - private int mGLTextureId = NO_IMAGE; - private SurfaceTexture mSurfaceTexture = null; - private final FloatBuffer mGLCubeBuffer; - private final FloatBuffer mGLTextureBuffer; - private IntBuffer mGLRgbBuffer; + private int glTextureId = NO_IMAGE; + private SurfaceTexture surfaceTexture = null; + private final FloatBuffer glCubeBuffer; + private final FloatBuffer glTextureBuffer; + private IntBuffer glRgbBuffer; - private int mOutputWidth; - private int mOutputHeight; - private int mImageWidth; - private int mImageHeight; - private int mAddedPadding; + private int outputWidth; + private int outputHeight; + private int imageWidth; + private int imageHeight; + private int addedPadding; - private final Queue mRunOnDraw; - private final Queue mRunOnDrawEnd; - private Rotation mRotation; - private boolean mFlipHorizontal; - private boolean mFlipVertical; - private GPUImage.ScaleType mScaleType = GPUImage.ScaleType.CENTER_CROP; + private final Queue runOnDraw; + private final Queue runOnDrawEnd; + private Rotation rotation; + private boolean flipHorizontal; + private boolean flipVertical; + private GPUImage.ScaleType scaleType = GPUImage.ScaleType.CENTER_CROP; - private float mBackgroundRed = 0; - private float mBackgroundGreen = 0; - private float mBackgroundBlue = 0; + private float backgroundRed = 0; + private float backgroundGreen = 0; + private float backgroundBlue = 0; public GPUImageRenderer(final GPUImageFilter filter) { - mFilter = filter; - mRunOnDraw = new LinkedList(); - mRunOnDrawEnd = new LinkedList(); + this.filter = filter; + runOnDraw = new LinkedList<>(); + runOnDrawEnd = new LinkedList<>(); - mGLCubeBuffer = ByteBuffer.allocateDirect(CUBE.length * 4) + glCubeBuffer = ByteBuffer.allocateDirect(CUBE.length * 4) .order(ByteOrder.nativeOrder()) .asFloatBuffer(); - mGLCubeBuffer.put(CUBE).position(0); + glCubeBuffer.put(CUBE).position(0); - mGLTextureBuffer = ByteBuffer.allocateDirect(TEXTURE_NO_ROTATION.length * 4) + glTextureBuffer = ByteBuffer.allocateDirect(TEXTURE_NO_ROTATION.length * 4) .order(ByteOrder.nativeOrder()) .asFloatBuffer(); setRotation(Rotation.NORMAL, false, false); @@ -95,46 +97,46 @@ public GPUImageRenderer(final GPUImageFilter filter) { @Override public void onSurfaceCreated(final GL10 unused, final EGLConfig config) { - GLES20.glClearColor(mBackgroundRed, mBackgroundGreen, mBackgroundBlue, 1); + GLES20.glClearColor(backgroundRed, backgroundGreen, backgroundBlue, 1); GLES20.glDisable(GLES20.GL_DEPTH_TEST); - mFilter.init(); + filter.ifNeedInit(); } @Override public void onSurfaceChanged(final GL10 gl, final int width, final int height) { - mOutputWidth = width; - mOutputHeight = height; + outputWidth = width; + outputHeight = height; GLES20.glViewport(0, 0, width, height); - GLES20.glUseProgram(mFilter.getProgram()); - mFilter.onOutputSizeChanged(width, height); + GLES20.glUseProgram(filter.getProgram()); + filter.onOutputSizeChanged(width, height); adjustImageScaling(); - synchronized (mSurfaceChangedWaiter) { - mSurfaceChangedWaiter.notifyAll(); + synchronized (surfaceChangedWaiter) { + surfaceChangedWaiter.notifyAll(); } } @Override public void onDrawFrame(final GL10 gl) { GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); - runAll(mRunOnDraw); - mFilter.onDraw(mGLTextureId, mGLCubeBuffer, mGLTextureBuffer); - runAll(mRunOnDrawEnd); - if (mSurfaceTexture != null) { - mSurfaceTexture.updateTexImage(); + runAll(runOnDraw); + filter.onDraw(glTextureId, glCubeBuffer, glTextureBuffer); + runAll(runOnDrawEnd); + if (surfaceTexture != null) { + surfaceTexture.updateTexImage(); } } /** * Sets the background color * - * @param red red color value + * @param red red color value * @param green green color value - * @param blue red color value + * @param blue red color value */ public void setBackgroundColor(float red, float green, float blue) { - mBackgroundRed = red; - mBackgroundGreen = green; - mBackgroundBlue = blue; + backgroundRed = red; + backgroundGreen = green; + backgroundBlue = blue; } private void runAll(Queue queue) { @@ -148,21 +150,23 @@ private void runAll(Queue queue) { @Override public void onPreviewFrame(final byte[] data, final Camera camera) { final Size previewSize = camera.getParameters().getPreviewSize(); - if (mGLRgbBuffer == null) { - mGLRgbBuffer = IntBuffer.allocate(previewSize.width * previewSize.height); + onPreviewFrame(data, previewSize.width, previewSize.height); + } + + public void onPreviewFrame(final byte[] data, final int width, final int height) { + if (glRgbBuffer == null) { + glRgbBuffer = IntBuffer.allocate(width * height); } - if (mRunOnDraw.isEmpty()) { + if (runOnDraw.isEmpty()) { runOnDraw(new Runnable() { @Override public void run() { - GPUImageNativeLibrary.YUVtoRBGA(data, previewSize.width, previewSize.height, - mGLRgbBuffer.array()); - mGLTextureId = OpenGlUtils.loadTexture(mGLRgbBuffer, previewSize, mGLTextureId); - camera.addCallbackBuffer(data); - - if (mImageWidth != previewSize.width) { - mImageWidth = previewSize.width; - mImageHeight = previewSize.height; + GPUImageNativeLibrary.YUVtoRBGA(data, width, height, glRgbBuffer.array()); + glTextureId = OpenGlUtils.loadTexture(glRgbBuffer, width, height, glTextureId); + + if (imageWidth != width) { + imageWidth = width; + imageHeight = height; adjustImageScaling(); } } @@ -176,9 +180,9 @@ public void setUpSurfaceTexture(final Camera camera) { public void run() { int[] textures = new int[1]; GLES20.glGenTextures(1, textures, 0); - mSurfaceTexture = new SurfaceTexture(textures[0]); + surfaceTexture = new SurfaceTexture(textures[0]); try { - camera.setPreviewTexture(mSurfaceTexture); + camera.setPreviewTexture(surfaceTexture); camera.setPreviewCallback(GPUImageRenderer.this); camera.startPreview(); } catch (IOException e) { @@ -193,14 +197,14 @@ public void setFilter(final GPUImageFilter filter) { @Override public void run() { - final GPUImageFilter oldFilter = mFilter; - mFilter = filter; + final GPUImageFilter oldFilter = GPUImageRenderer.this.filter; + GPUImageRenderer.this.filter = filter; if (oldFilter != null) { oldFilter.destroy(); } - mFilter.init(); - GLES20.glUseProgram(mFilter.getProgram()); - mFilter.onOutputSizeChanged(mOutputWidth, mOutputHeight); + GPUImageRenderer.this.filter.ifNeedInit(); + GLES20.glUseProgram(GPUImageRenderer.this.filter.getProgram()); + GPUImageRenderer.this.filter.onOutputSizeChanged(outputWidth, outputHeight); } }); } @@ -211,9 +215,9 @@ public void deleteImage() { @Override public void run() { GLES20.glDeleteTextures(1, new int[]{ - mGLTextureId + glTextureId }, 0); - mGLTextureId = NO_IMAGE; + glTextureId = NO_IMAGE; } }); } @@ -235,58 +239,59 @@ public void run() { if (bitmap.getWidth() % 2 == 1) { resizedBitmap = Bitmap.createBitmap(bitmap.getWidth() + 1, bitmap.getHeight(), Bitmap.Config.ARGB_8888); + resizedBitmap.setDensity(bitmap.getDensity()); Canvas can = new Canvas(resizedBitmap); can.drawARGB(0x00, 0x00, 0x00, 0x00); can.drawBitmap(bitmap, 0, 0, null); - mAddedPadding = 1; + addedPadding = 1; } else { - mAddedPadding = 0; + addedPadding = 0; } - mGLTextureId = OpenGlUtils.loadTexture( - resizedBitmap != null ? resizedBitmap : bitmap, mGLTextureId, recycle); + glTextureId = OpenGlUtils.loadTexture( + resizedBitmap != null ? resizedBitmap : bitmap, glTextureId, recycle); if (resizedBitmap != null) { resizedBitmap.recycle(); } - mImageWidth = bitmap.getWidth(); - mImageHeight = bitmap.getHeight(); + imageWidth = bitmap.getWidth(); + imageHeight = bitmap.getHeight(); adjustImageScaling(); } }); } public void setScaleType(GPUImage.ScaleType scaleType) { - mScaleType = scaleType; + this.scaleType = scaleType; } protected int getFrameWidth() { - return mOutputWidth; + return outputWidth; } protected int getFrameHeight() { - return mOutputHeight; + return outputHeight; } private void adjustImageScaling() { - float outputWidth = mOutputWidth; - float outputHeight = mOutputHeight; - if (mRotation == Rotation.ROTATION_270 || mRotation == Rotation.ROTATION_90) { - outputWidth = mOutputHeight; - outputHeight = mOutputWidth; + float outputWidth = this.outputWidth; + float outputHeight = this.outputHeight; + if (rotation == Rotation.ROTATION_270 || rotation == Rotation.ROTATION_90) { + outputWidth = this.outputHeight; + outputHeight = this.outputWidth; } - float ratio1 = outputWidth / mImageWidth; - float ratio2 = outputHeight / mImageHeight; + float ratio1 = outputWidth / imageWidth; + float ratio2 = outputHeight / imageHeight; float ratioMax = Math.max(ratio1, ratio2); - int imageWidthNew = Math.round(mImageWidth * ratioMax); - int imageHeightNew = Math.round(mImageHeight * ratioMax); + int imageWidthNew = Math.round(imageWidth * ratioMax); + int imageHeightNew = Math.round(imageHeight * ratioMax); float ratioWidth = imageWidthNew / outputWidth; float ratioHeight = imageHeightNew / outputHeight; float[] cube = CUBE; - float[] textureCords = TextureRotationUtil.getRotation(mRotation, mFlipHorizontal, mFlipVertical); - if (mScaleType == GPUImage.ScaleType.CENTER_CROP) { + float[] textureCords = TextureRotationUtil.getRotation(rotation, flipHorizontal, flipVertical); + if (scaleType == GPUImage.ScaleType.CENTER_CROP) { float distHorizontal = (1 - 1 / ratioWidth) / 2; float distVertical = (1 - 1 / ratioHeight) / 2; textureCords = new float[]{ @@ -304,10 +309,10 @@ private void adjustImageScaling() { }; } - mGLCubeBuffer.clear(); - mGLCubeBuffer.put(cube).position(0); - mGLTextureBuffer.clear(); - mGLTextureBuffer.put(textureCords).position(0); + glCubeBuffer.clear(); + glCubeBuffer.put(cube).position(0); + glTextureBuffer.clear(); + glTextureBuffer.put(textureCords).position(0); } private float addDistance(float coordinate, float distance) { @@ -315,43 +320,43 @@ private float addDistance(float coordinate, float distance) { } public void setRotationCamera(final Rotation rotation, final boolean flipHorizontal, - final boolean flipVertical) { + final boolean flipVertical) { setRotation(rotation, flipVertical, flipHorizontal); } public void setRotation(final Rotation rotation) { - mRotation = rotation; + this.rotation = rotation; adjustImageScaling(); } public void setRotation(final Rotation rotation, final boolean flipHorizontal, final boolean flipVertical) { - mFlipHorizontal = flipHorizontal; - mFlipVertical = flipVertical; + this.flipHorizontal = flipHorizontal; + this.flipVertical = flipVertical; setRotation(rotation); } public Rotation getRotation() { - return mRotation; + return rotation; } public boolean isFlippedHorizontally() { - return mFlipHorizontal; + return flipHorizontal; } public boolean isFlippedVertically() { - return mFlipVertical; + return flipVertical; } protected void runOnDraw(final Runnable runnable) { - synchronized (mRunOnDraw) { - mRunOnDraw.add(runnable); + synchronized (runOnDraw) { + runOnDraw.add(runnable); } } protected void runOnDrawEnd(final Runnable runnable) { - synchronized (mRunOnDrawEnd) { - mRunOnDrawEnd.add(runnable); + synchronized (runOnDrawEnd) { + runOnDrawEnd.add(runnable); } } } diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageView.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/GPUImageView.java similarity index 55% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageView.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/GPUImageView.java index cc6a02472..a4fbacd8e 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageView.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/GPUImageView.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,17 +17,21 @@ package jp.co.cyberagent.android.gpuimage; import android.content.Context; +import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.Color; -import android.graphics.drawable.ColorDrawable; -import android.graphics.drawable.Drawable; +import android.hardware.Camera; import android.media.MediaScannerConnection; import android.net.Uri; -import android.opengl.GLES20; import android.opengl.GLSurfaceView; -import android.os.*; +import android.os.AsyncTask; +import android.os.Build; +import android.os.Environment; +import android.os.Handler; +import android.os.Looper; import android.util.AttributeSet; import android.view.Gravity; +import android.view.View; import android.view.ViewTreeObserver; import android.widget.FrameLayout; import android.widget.ProgressBar; @@ -35,16 +39,26 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; -import java.nio.IntBuffer; import java.util.concurrent.Semaphore; +import jp.co.cyberagent.android.gpuimage.filter.GPUImageFilter; +import jp.co.cyberagent.android.gpuimage.util.Rotation; + +import static jp.co.cyberagent.android.gpuimage.GPUImage.SURFACE_TYPE_SURFACE_VIEW; +import static jp.co.cyberagent.android.gpuimage.GPUImage.SURFACE_TYPE_TEXTURE_VIEW; + public class GPUImageView extends FrameLayout { - private GLSurfaceView mGLSurfaceView; - private GPUImage mGPUImage; - private GPUImageFilter mFilter; - public Size mForceSize = null; - private float mRatio = 0.0f; + private int surfaceType = SURFACE_TYPE_SURFACE_VIEW; + private View surfaceView; + private GPUImage gpuImage; + private boolean isShowLoading = true; + private GPUImageFilter filter; + public Size forceSize = null; + private float ratio = 0.0f; + + public final static int RENDERMODE_WHEN_DIRTY = 0; + public final static int RENDERMODE_CONTINUOUSLY = 1; public GPUImageView(Context context) { super(context); @@ -57,26 +71,40 @@ public GPUImageView(Context context, AttributeSet attrs) { } private void init(Context context, AttributeSet attrs) { - mGLSurfaceView = new GPUImageGLSurfaceView(context, attrs); - addView(mGLSurfaceView); - mGPUImage = new GPUImage(getContext()); - mGPUImage.setGLSurfaceView(mGLSurfaceView); + if (attrs != null) { + TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.GPUImageView, 0, 0); + try { + surfaceType = a.getInt(R.styleable.GPUImageView_gpuimage_surface_type, surfaceType); + isShowLoading = a.getBoolean(R.styleable.GPUImageView_gpuimage_show_loading, isShowLoading); + } finally { + a.recycle(); + } + } + gpuImage = new GPUImage(context); + if (surfaceType == SURFACE_TYPE_TEXTURE_VIEW) { + surfaceView = new GPUImageGLTextureView(context, attrs); + gpuImage.setGLTextureView((GLTextureView) surfaceView); + } else { + surfaceView = new GPUImageGLSurfaceView(context, attrs); + gpuImage.setGLSurfaceView((GLSurfaceView) surfaceView); + } + addView(surfaceView); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - if (mRatio != 0.0f) { + if (ratio != 0.0f) { int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); int newHeight; int newWidth; - if (width / mRatio < height) { + if (width / ratio < height) { newWidth = width; - newHeight = Math.round(width / mRatio); + newHeight = Math.round(width / ratio); } else { newHeight = height; - newWidth = Math.round(height * mRatio); + newWidth = Math.round(height * ratio); } int newWidthSpec = MeasureSpec.makeMeasureSpec(newWidth, MeasureSpec.EXACTLY); @@ -93,25 +121,87 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { * @return used GPUImage instance */ public GPUImage getGPUImage() { - return mGPUImage; + return gpuImage; + } + + /** + * Deprecated: Please call + * {@link GPUImageView#updatePreviewFrame(byte[], int, int)} frame by frame + *

+ * Sets the up camera to be connected to GPUImage to get a filtered preview. + * + * @param camera the camera + */ + @Deprecated + public void setUpCamera(final Camera camera) { + gpuImage.setUpCamera(camera); + } + + /** + * Deprecated: Please call + * {@link GPUImageView#updatePreviewFrame(byte[], int, int)} frame by frame + *

+ * Sets the up camera to be connected to GPUImage to get a filtered preview. + * + * @param camera the camera + * @param degrees by how many degrees the image should be rotated + * @param flipHorizontal if the image should be flipped horizontally + * @param flipVertical if the image should be flipped vertically + */ + @Deprecated + public void setUpCamera(final Camera camera, final int degrees, final boolean flipHorizontal, + final boolean flipVertical) { + gpuImage.setUpCamera(camera, degrees, flipHorizontal, flipVertical); + } + + /** + * Update camera preview frame with YUV format data. + * + * @param data Camera preview YUV data for frame. + * @param width width of camera preview + * @param height height of camera preview + */ + public void updatePreviewFrame(byte[] data, int width, int height) { + gpuImage.updatePreviewFrame(data, width, height); } /** * Sets the background color * - * @param red red color value + * @param red red color value * @param green green color value - * @param blue red color value + * @param blue red color value */ public void setBackgroundColor(float red, float green, float blue) { - mGPUImage.setBackgroundColor(red, green, blue); + gpuImage.setBackgroundColor(red, green, blue); + } + + /** + * Set the rendering mode. When renderMode is + * RENDERMODE_CONTINUOUSLY, the renderer is called + * repeatedly to re-render the scene. When renderMode + * is RENDERMODE_WHEN_DIRTY, the renderer only rendered when the surface + * is created, or when {@link #requestRender} is called. Defaults to RENDERMODE_CONTINUOUSLY. + * + * @param renderMode one of the RENDERMODE_X constants + * @see #RENDERMODE_CONTINUOUSLY + * @see #RENDERMODE_WHEN_DIRTY + * @see GLSurfaceView#setRenderMode(int) + * @see GLTextureView#setRenderMode(int) + */ + public void setRenderMode(int renderMode) { + if (surfaceView instanceof GLSurfaceView) { + ((GLSurfaceView) surfaceView).setRenderMode(renderMode); + } else if (surfaceView instanceof GLTextureView) { + ((GLTextureView) surfaceView).setRenderMode(renderMode); + } } // TODO Should be an xml attribute. But then GPUImage can not be distributed as .jar anymore. public void setRatio(float ratio) { - mRatio = ratio; - mGLSurfaceView.requestLayout(); - mGPUImage.deleteImage(); + this.ratio = ratio; + surfaceView.requestLayout(); + gpuImage.deleteImage(); } /** @@ -120,7 +210,7 @@ public void setRatio(float ratio) { * @param scaleType the new ScaleType */ public void setScaleType(GPUImage.ScaleType scaleType) { - mGPUImage.setScaleType(scaleType); + gpuImage.setScaleType(scaleType); } /** @@ -129,7 +219,7 @@ public void setScaleType(GPUImage.ScaleType scaleType) { * @param rotation new rotation */ public void setRotation(Rotation rotation) { - mGPUImage.setRotation(rotation); + gpuImage.setRotation(rotation); requestRender(); } @@ -139,8 +229,8 @@ public void setRotation(Rotation rotation) { * @param filter Filter that should be applied on the image. */ public void setFilter(GPUImageFilter filter) { - mFilter = filter; - mGPUImage.setFilter(filter); + this.filter = filter; + gpuImage.setFilter(filter); requestRender(); } @@ -150,7 +240,7 @@ public void setFilter(GPUImageFilter filter) { * @return the current filter */ public GPUImageFilter getFilter() { - return mFilter; + return filter; } /** @@ -159,7 +249,7 @@ public GPUImageFilter getFilter() { * @param bitmap the new image */ public void setImage(final Bitmap bitmap) { - mGPUImage.setImage(bitmap); + gpuImage.setImage(bitmap); } /** @@ -168,7 +258,7 @@ public void setImage(final Bitmap bitmap) { * @param uri the uri of the new image */ public void setImage(final Uri uri) { - mGPUImage.setImage(uri); + gpuImage.setImage(uri); } /** @@ -177,11 +267,15 @@ public void setImage(final Uri uri) { * @param file the file of the new image */ public void setImage(final File file) { - mGPUImage.setImage(file); + gpuImage.setImage(file); } public void requestRender() { - mGLSurfaceView.requestRender(); + if (surfaceView instanceof GLSurfaceView) { + ((GLSurfaceView) surfaceView).requestRender(); + } else if (surfaceView instanceof GLTextureView) { + ((GLTextureView) surfaceView).requestRender(); + } } /** @@ -192,12 +286,12 @@ public void requestRender() { * listener. * * @param folderName the folder name - * @param fileName the file name - * @param listener the listener + * @param fileName the file name + * @param listener the listener */ public void saveToPictures(final String folderName, final String fileName, final OnPictureSavedListener listener) { - new SaveTask(folderName, fileName, listener).execute(); + new SaveTask(folderName, fileName, listener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } /** @@ -216,7 +310,7 @@ public void saveToPictures(final String folderName, final String fileName, public void saveToPictures(final String folderName, final String fileName, int width, int height, final OnPictureSavedListener listener) { - new SaveTask(folderName, fileName, width, height, listener).execute(); + new SaveTask(folderName, fileName, width, height, listener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } /** @@ -233,7 +327,7 @@ public Bitmap capture(final int width, final int height) throws InterruptedExcep throw new IllegalStateException("Do not call this method from the UI thread!"); } - mForceSize = new Size(width, height); + forceSize = new Size(width, height); final Semaphore waiter = new Semaphore(0); @@ -249,19 +343,23 @@ public void onGlobalLayout() { waiter.release(); } }); + post(new Runnable() { @Override public void run() { - // Show loading - addView(new LoadingView(getContext())); - - mGLSurfaceView.requestLayout(); + // Optionally, show loading view: + if (isShowLoading) { + addView(new LoadingView(getContext())); + } + // Request layout to release waiter: + surfaceView.requestLayout(); } }); + waiter.acquire(); // Run one render pass - mGPUImage.runOnGLThread(new Runnable() { + gpuImage.runOnGLThread(new Runnable() { @Override public void run() { waiter.release(); @@ -272,75 +370,75 @@ public void run() { Bitmap bitmap = capture(); - mForceSize = null; + forceSize = null; post(new Runnable() { @Override public void run() { - mGLSurfaceView.requestLayout(); + surfaceView.requestLayout(); } }); requestRender(); - postDelayed(new Runnable() { - @Override - public void run() { - // Remove loading view - removeViewAt(1); - } - }, 300); + if (isShowLoading) { + postDelayed(new Runnable() { + @Override + public void run() { + // Remove loading view + removeViewAt(1); + } + }, 300); + } return bitmap; } /** * Capture the current image with the size as it is displayed and retrieve it as Bitmap. + * * @return current output as Bitmap * @throws InterruptedException */ public Bitmap capture() throws InterruptedException { final Semaphore waiter = new Semaphore(0); - final int width = mGLSurfaceView.getMeasuredWidth(); - final int height = mGLSurfaceView.getMeasuredHeight(); + final int width = surfaceView.getMeasuredWidth(); + final int height = surfaceView.getMeasuredHeight(); // Take picture on OpenGL thread - final int[] pixelMirroredArray = new int[width * height]; - mGPUImage.runOnGLThread(new Runnable() { + final Bitmap resultBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + gpuImage.runOnGLThread(new Runnable() { @Override public void run() { - final IntBuffer pixelBuffer = IntBuffer.allocate(width * height); - GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, pixelBuffer); - int[] pixelArray = pixelBuffer.array(); - - // Convert upside down mirror-reversed image to right-side up normal image. - for (int i = 0; i < height; i++) { - for (int j = 0; j < width; j++) { - pixelMirroredArray[(height - i - 1) * width + j] = pixelArray[i * width + j]; - } - } + GPUImageNativeLibrary.adjustBitmap(resultBitmap); waiter.release(); } }); requestRender(); waiter.acquire(); - Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); - bitmap.copyPixelsFromBuffer(IntBuffer.wrap(pixelMirroredArray)); - return bitmap; + return resultBitmap; } /** - * Pauses the GLSurfaceView. + * Pauses the Surface. */ public void onPause() { - mGLSurfaceView.onPause(); + if (surfaceView instanceof GLSurfaceView) { + ((GLSurfaceView) surfaceView).onPause(); + } else if (surfaceView instanceof GLTextureView) { + ((GLTextureView) surfaceView).onPause(); + } } /** - * Resumes the GLSurfaceView. + * Resumes the Surface. */ public void onResume() { - mGLSurfaceView.onResume(); + if (surfaceView instanceof GLSurfaceView) { + ((GLSurfaceView) surfaceView).onResume(); + } else if (surfaceView instanceof GLTextureView) { + ((GLTextureView) surfaceView).onResume(); + } } public static class Size { @@ -364,9 +462,29 @@ public GPUImageGLSurfaceView(Context context, AttributeSet attrs) { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - if (mForceSize != null) { - super.onMeasure(MeasureSpec.makeMeasureSpec(mForceSize.width, MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(mForceSize.height, MeasureSpec.EXACTLY)); + if (forceSize != null) { + super.onMeasure(MeasureSpec.makeMeasureSpec(forceSize.width, MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(forceSize.height, MeasureSpec.EXACTLY)); + } else { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + } + } + + private class GPUImageGLTextureView extends GLTextureView { + public GPUImageGLTextureView(Context context) { + super(context); + } + + public GPUImageGLTextureView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + if (forceSize != null) { + super.onMeasure(MeasureSpec.makeMeasureSpec(forceSize.width, MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(forceSize.height, MeasureSpec.EXACTLY)); } else { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @@ -399,12 +517,12 @@ private void init() { } private class SaveTask extends AsyncTask { - private final String mFolderName; - private final String mFileName; - private final int mWidth; - private final int mHeight; - private final OnPictureSavedListener mListener; - private final Handler mHandler; + private final String folderName; + private final String fileName; + private final int width; + private final int height; + private final OnPictureSavedListener listener; + private final Handler handler; public SaveTask(final String folderName, final String fileName, final OnPictureSavedListener listener) { @@ -413,19 +531,19 @@ public SaveTask(final String folderName, final String fileName, public SaveTask(final String folderName, final String fileName, int width, int height, final OnPictureSavedListener listener) { - mFolderName = folderName; - mFileName = fileName; - mWidth = width; - mHeight = height; - mListener = listener; - mHandler = new Handler(); + this.folderName = folderName; + this.fileName = fileName; + this.width = width; + this.height = height; + this.listener = listener; + handler = new Handler(); } @Override protected Void doInBackground(final Void... params) { try { - Bitmap result = mWidth != 0 ? capture(mWidth, mHeight) : capture(); - saveImage(mFolderName, mFileName, result); + Bitmap result = width != 0 ? capture(width, height) : capture(); + saveImage(folderName, fileName, result); } catch (InterruptedException e) { e.printStackTrace(); } @@ -433,8 +551,7 @@ protected Void doInBackground(final Void... params) { } private void saveImage(final String folderName, final String fileName, final Bitmap image) { - File path = Environment - .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); + File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); File file = new File(path, folderName + "/" + fileName); try { file.getParentFile().mkdirs(); @@ -446,12 +563,12 @@ private void saveImage(final String folderName, final String fileName, final Bit new MediaScannerConnection.OnScanCompletedListener() { @Override public void onScanCompleted(final String path, final Uri uri) { - if (mListener != null) { - mHandler.post(new Runnable() { + if (listener != null) { + handler.post(new Runnable() { @Override public void run() { - mListener.onPictureSaved(uri); + listener.onPictureSaved(uri); } }); } diff --git a/library/src/jp/co/cyberagent/android/gpuimage/PixelBuffer.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/PixelBuffer.java similarity index 58% rename from library/src/jp/co/cyberagent/android/gpuimage/PixelBuffer.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/PixelBuffer.java index ac23f5990..193ce1e15 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/PixelBuffer.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/PixelBuffer.java @@ -1,13 +1,24 @@ /* - * Copyright (C) 2012 CyberAgent - * Copyright (C) 2010 jsemler - * + * Copyright (C) 2018 CyberAgent, Inc. + * Copyright (C) 2010 jsemler + * * Original publication without License * http://www.anddev.org/android-2d-3d-graphics-opengl-tutorials-f2/possible-to-do-opengl-off-screen-rendering-in-android-t13232.html#p41662 */ package jp.co.cyberagent.android.gpuimage; +import android.graphics.Bitmap; +import android.opengl.GLSurfaceView; +import android.util.Log; + +import javax.microedition.khronos.egl.EGL10; +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.egl.EGLContext; +import javax.microedition.khronos.egl.EGLDisplay; +import javax.microedition.khronos.egl.EGLSurface; +import javax.microedition.khronos.opengles.GL10; + import static javax.microedition.khronos.egl.EGL10.EGL_ALPHA_SIZE; import static javax.microedition.khronos.egl.EGL10.EGL_BLUE_SIZE; import static javax.microedition.khronos.egl.EGL10.EGL_DEFAULT_DISPLAY; @@ -19,78 +30,63 @@ import static javax.microedition.khronos.egl.EGL10.EGL_RED_SIZE; import static javax.microedition.khronos.egl.EGL10.EGL_STENCIL_SIZE; import static javax.microedition.khronos.egl.EGL10.EGL_WIDTH; -import static javax.microedition.khronos.opengles.GL10.GL_RGBA; -import static javax.microedition.khronos.opengles.GL10.GL_UNSIGNED_BYTE; - -import java.nio.IntBuffer; - -import javax.microedition.khronos.egl.EGL10; -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.egl.EGLContext; -import javax.microedition.khronos.egl.EGLDisplay; -import javax.microedition.khronos.egl.EGLSurface; -import javax.microedition.khronos.opengles.GL10; - -import android.graphics.Bitmap; -import android.opengl.GLSurfaceView; -import android.util.Log; public class PixelBuffer { - final static String TAG = "PixelBuffer"; - final static boolean LIST_CONFIGS = false; + private final static String TAG = "PixelBuffer"; + private final static boolean LIST_CONFIGS = false; - GLSurfaceView.Renderer mRenderer; // borrow this interface - int mWidth, mHeight; - Bitmap mBitmap; + private GLSurfaceView.Renderer renderer; // borrow this interface + private int width, height; + private Bitmap bitmap; - EGL10 mEGL; - EGLDisplay mEGLDisplay; - EGLConfig[] mEGLConfigs; - EGLConfig mEGLConfig; - EGLContext mEGLContext; - EGLSurface mEGLSurface; - GL10 mGL; + private EGL10 egl10; + private EGLDisplay eglDisplay; + private EGLConfig[] eglConfigs; + private EGLConfig eglConfig; + private EGLContext eglContext; + private EGLSurface eglSurface; + private GL10 gl10; - String mThreadOwner; + private String mThreadOwner; public PixelBuffer(final int width, final int height) { - mWidth = width; - mHeight = height; + this.width = width; + this.height = height; int[] version = new int[2]; - int[] attribList = new int[] { - EGL_WIDTH, mWidth, - EGL_HEIGHT, mHeight, + int[] attribList = new int[]{ + EGL_WIDTH, this.width, + EGL_HEIGHT, this.height, EGL_NONE }; // No error checking performed, minimum required code to elucidate logic - mEGL = (EGL10) EGLContext.getEGL(); - mEGLDisplay = mEGL.eglGetDisplay(EGL_DEFAULT_DISPLAY); - mEGL.eglInitialize(mEGLDisplay, version); - mEGLConfig = chooseConfig(); // Choosing a config is a little more - // complicated + egl10 = (EGL10) EGLContext.getEGL(); + eglDisplay = egl10.eglGetDisplay(EGL_DEFAULT_DISPLAY); + egl10.eglInitialize(eglDisplay, version); + eglConfig = chooseConfig(); // Choosing a config is a little more + // complicated - // mEGLContext = mEGL.eglCreateContext(mEGLDisplay, mEGLConfig, + // eglContext = egl10.eglCreateContext(eglDisplay, eglConfig, // EGL_NO_CONTEXT, null); int EGL_CONTEXT_CLIENT_VERSION = 0x3098; int[] attrib_list = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE }; - mEGLContext = mEGL.eglCreateContext(mEGLDisplay, mEGLConfig, EGL_NO_CONTEXT, attrib_list); + eglContext = egl10.eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, attrib_list); - mEGLSurface = mEGL.eglCreatePbufferSurface(mEGLDisplay, mEGLConfig, attribList); - mEGL.eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext); + eglSurface = egl10.eglCreatePbufferSurface(eglDisplay, eglConfig, attribList); + egl10.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext); - mGL = (GL10) mEGLContext.getGL(); + gl10 = (GL10) eglContext.getGL(); // Record thread owner of OpenGL context mThreadOwner = Thread.currentThread().getName(); } public void setRenderer(final GLSurfaceView.Renderer renderer) { - mRenderer = renderer; + this.renderer = renderer; // Does this thread own the OpenGL context? if (!Thread.currentThread().getName().equals(mThreadOwner)) { @@ -99,13 +95,13 @@ public void setRenderer(final GLSurfaceView.Renderer renderer) { } // Call the renderer initialization routines - mRenderer.onSurfaceCreated(mGL, mEGLConfig); - mRenderer.onSurfaceChanged(mGL, mWidth, mHeight); + this.renderer.onSurfaceCreated(gl10, eglConfig); + this.renderer.onSurfaceChanged(gl10, width, height); } public Bitmap getBitmap() { // Do we have a renderer? - if (mRenderer == null) { + if (renderer == null) { Log.e(TAG, "getBitmap: Renderer was not set."); return null; } @@ -118,25 +114,25 @@ public Bitmap getBitmap() { // Call the renderer draw routine (it seems that some filters do not // work if this is only called once) - mRenderer.onDrawFrame(mGL); - mRenderer.onDrawFrame(mGL); + renderer.onDrawFrame(gl10); + renderer.onDrawFrame(gl10); convertToBitmap(); - return mBitmap; + return bitmap; } public void destroy() { - mRenderer.onDrawFrame(mGL); - mRenderer.onDrawFrame(mGL); - mEGL.eglMakeCurrent(mEGLDisplay, EGL10.EGL_NO_SURFACE, + renderer.onDrawFrame(gl10); + renderer.onDrawFrame(gl10); + egl10.eglMakeCurrent(eglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); - mEGL.eglDestroySurface(mEGLDisplay, mEGLSurface); - mEGL.eglDestroyContext(mEGLDisplay, mEGLContext); - mEGL.eglTerminate(mEGLDisplay); + egl10.eglDestroySurface(eglDisplay, eglSurface); + egl10.eglDestroyContext(eglDisplay, eglContext); + egl10.eglTerminate(eglDisplay); } private EGLConfig chooseConfig() { - int[] attribList = new int[] { + int[] attribList = new int[]{ EGL_DEPTH_SIZE, 0, EGL_STENCIL_SIZE, 0, EGL_RED_SIZE, 8, @@ -150,22 +146,22 @@ private EGLConfig chooseConfig() { // No error checking performed, minimum required code to elucidate logic // Expand on this logic to be more selective in choosing a configuration int[] numConfig = new int[1]; - mEGL.eglChooseConfig(mEGLDisplay, attribList, null, 0, numConfig); + egl10.eglChooseConfig(eglDisplay, attribList, null, 0, numConfig); int configSize = numConfig[0]; - mEGLConfigs = new EGLConfig[configSize]; - mEGL.eglChooseConfig(mEGLDisplay, attribList, mEGLConfigs, configSize, numConfig); + eglConfigs = new EGLConfig[configSize]; + egl10.eglChooseConfig(eglDisplay, attribList, eglConfigs, configSize, numConfig); if (LIST_CONFIGS) { listConfig(); } - return mEGLConfigs[0]; // Best match is probably the first configuration + return eglConfigs[0]; // Best match is probably the first configuration } private void listConfig() { Log.i(TAG, "Config List {"); - for (EGLConfig config : mEGLConfigs) { + for (EGLConfig config : eglConfigs) { int d, s, r, g, b, a; // Expand on this logic to dump other attributes @@ -184,27 +180,12 @@ private void listConfig() { private int getConfigAttrib(final EGLConfig config, final int attribute) { int[] value = new int[1]; - return mEGL.eglGetConfigAttrib(mEGLDisplay, config, + return egl10.eglGetConfigAttrib(eglDisplay, config, attribute, value) ? value[0] : 0; } private void convertToBitmap() { - int[] iat = new int[mWidth * mHeight]; - IntBuffer ib = IntBuffer.allocate(mWidth * mHeight); - mGL.glReadPixels(0, 0, mWidth, mHeight, GL_RGBA, GL_UNSIGNED_BYTE, ib); - int[] ia = ib.array(); - - //Stupid ! - // Convert upside down mirror-reversed image to right-side up normal - // image. - for (int i = 0; i < mHeight; i++) { - for (int j = 0; j < mWidth; j++) { - iat[(mHeight - i - 1) * mWidth + j] = ia[i * mWidth + j]; - } - } - - - mBitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888); - mBitmap.copyPixelsFromBuffer(IntBuffer.wrap(iat)); + bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + GPUImageNativeLibrary.adjustBitmap(bitmap); } } diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImage3x3ConvolutionFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImage3x3ConvolutionFilter.java similarity index 56% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImage3x3ConvolutionFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImage3x3ConvolutionFilter.java index 0c5e5a03d..e6485e966 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImage3x3ConvolutionFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImage3x3ConvolutionFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; import android.opengl.GLES20; @@ -23,58 +23,58 @@ */ public class GPUImage3x3ConvolutionFilter extends GPUImage3x3TextureSamplingFilter { public static final String THREE_X_THREE_TEXTURE_SAMPLING_FRAGMENT_SHADER = "" + - "precision highp float;\n" + - "\n" + - "uniform sampler2D inputImageTexture;\n" + - "\n" + - "uniform mediump mat3 convolutionMatrix;\n" + - "\n" + - "varying vec2 textureCoordinate;\n" + - "varying vec2 leftTextureCoordinate;\n" + - "varying vec2 rightTextureCoordinate;\n" + - "\n" + - "varying vec2 topTextureCoordinate;\n" + - "varying vec2 topLeftTextureCoordinate;\n" + - "varying vec2 topRightTextureCoordinate;\n" + - "\n" + - "varying vec2 bottomTextureCoordinate;\n" + - "varying vec2 bottomLeftTextureCoordinate;\n" + - "varying vec2 bottomRightTextureCoordinate;\n" + - "\n" + - "void main()\n" + - "{\n" + - " mediump vec4 bottomColor = texture2D(inputImageTexture, bottomTextureCoordinate);\n" + - " mediump vec4 bottomLeftColor = texture2D(inputImageTexture, bottomLeftTextureCoordinate);\n" + - " mediump vec4 bottomRightColor = texture2D(inputImageTexture, bottomRightTextureCoordinate);\n" + - " mediump vec4 centerColor = texture2D(inputImageTexture, textureCoordinate);\n" + - " mediump vec4 leftColor = texture2D(inputImageTexture, leftTextureCoordinate);\n" + - " mediump vec4 rightColor = texture2D(inputImageTexture, rightTextureCoordinate);\n" + - " mediump vec4 topColor = texture2D(inputImageTexture, topTextureCoordinate);\n" + - " mediump vec4 topRightColor = texture2D(inputImageTexture, topRightTextureCoordinate);\n" + - " mediump vec4 topLeftColor = texture2D(inputImageTexture, topLeftTextureCoordinate);\n" + - "\n" + - " mediump vec4 resultColor = topLeftColor * convolutionMatrix[0][0] + topColor * convolutionMatrix[0][1] + topRightColor * convolutionMatrix[0][2];\n" + - " resultColor += leftColor * convolutionMatrix[1][0] + centerColor * convolutionMatrix[1][1] + rightColor * convolutionMatrix[1][2];\n" + - " resultColor += bottomLeftColor * convolutionMatrix[2][0] + bottomColor * convolutionMatrix[2][1] + bottomRightColor * convolutionMatrix[2][2];\n" + - "\n" + - " gl_FragColor = resultColor;\n" + - "}"; - - private float[] mConvolutionKernel; - private int mUniformConvolutionMatrix; + "precision highp float;\n" + + "\n" + + "uniform sampler2D inputImageTexture;\n" + + "\n" + + "uniform mediump mat3 convolutionMatrix;\n" + + "\n" + + "varying vec2 textureCoordinate;\n" + + "varying vec2 leftTextureCoordinate;\n" + + "varying vec2 rightTextureCoordinate;\n" + + "\n" + + "varying vec2 topTextureCoordinate;\n" + + "varying vec2 topLeftTextureCoordinate;\n" + + "varying vec2 topRightTextureCoordinate;\n" + + "\n" + + "varying vec2 bottomTextureCoordinate;\n" + + "varying vec2 bottomLeftTextureCoordinate;\n" + + "varying vec2 bottomRightTextureCoordinate;\n" + + "\n" + + "void main()\n" + + "{\n" + + " mediump vec4 bottomColor = texture2D(inputImageTexture, bottomTextureCoordinate);\n" + + " mediump vec4 bottomLeftColor = texture2D(inputImageTexture, bottomLeftTextureCoordinate);\n" + + " mediump vec4 bottomRightColor = texture2D(inputImageTexture, bottomRightTextureCoordinate);\n" + + " mediump vec4 centerColor = texture2D(inputImageTexture, textureCoordinate);\n" + + " mediump vec4 leftColor = texture2D(inputImageTexture, leftTextureCoordinate);\n" + + " mediump vec4 rightColor = texture2D(inputImageTexture, rightTextureCoordinate);\n" + + " mediump vec4 topColor = texture2D(inputImageTexture, topTextureCoordinate);\n" + + " mediump vec4 topRightColor = texture2D(inputImageTexture, topRightTextureCoordinate);\n" + + " mediump vec4 topLeftColor = texture2D(inputImageTexture, topLeftTextureCoordinate);\n" + + "\n" + + " mediump vec4 resultColor = topLeftColor * convolutionMatrix[0][0] + topColor * convolutionMatrix[0][1] + topRightColor * convolutionMatrix[0][2];\n" + + " resultColor += leftColor * convolutionMatrix[1][0] + centerColor * convolutionMatrix[1][1] + rightColor * convolutionMatrix[1][2];\n" + + " resultColor += bottomLeftColor * convolutionMatrix[2][0] + bottomColor * convolutionMatrix[2][1] + bottomRightColor * convolutionMatrix[2][2];\n" + + "\n" + + " gl_FragColor = resultColor;\n" + + "}"; + + private float[] convolutionKernel; + private int uniformConvolutionMatrix; /** * Instantiates a new GPUimage3x3ConvolutionFilter with default values, that - * will look like the original image. + * will look like the original image. */ public GPUImage3x3ConvolutionFilter() { - this(new float[] { + this(new float[]{ 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f }); } - + /** * Instantiates a new GPUimage3x3ConvolutionFilter with given convolution kernel. * @@ -82,14 +82,19 @@ public GPUImage3x3ConvolutionFilter() { */ public GPUImage3x3ConvolutionFilter(final float[] convolutionKernel) { super(THREE_X_THREE_TEXTURE_SAMPLING_FRAGMENT_SHADER); - mConvolutionKernel = convolutionKernel; + this.convolutionKernel = convolutionKernel; } @Override public void onInit() { super.onInit(); - mUniformConvolutionMatrix = GLES20.glGetUniformLocation(getProgram(), "convolutionMatrix"); - setConvolutionKernel(mConvolutionKernel); + uniformConvolutionMatrix = GLES20.glGetUniformLocation(getProgram(), "convolutionMatrix"); + } + + @Override + public void onInitialized() { + super.onInitialized(); + setConvolutionKernel(convolutionKernel); } /** @@ -98,7 +103,7 @@ public void onInit() { * @param convolutionKernel the new convolution kernel */ public void setConvolutionKernel(final float[] convolutionKernel) { - mConvolutionKernel = convolutionKernel; - setUniformMatrix3f(mUniformConvolutionMatrix, mConvolutionKernel); + this.convolutionKernel = convolutionKernel; + setUniformMatrix3f(uniformConvolutionMatrix, this.convolutionKernel); } } diff --git a/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImage3x3TextureSamplingFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImage3x3TextureSamplingFilter.java new file mode 100644 index 000000000..ac6798908 --- /dev/null +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImage3x3TextureSamplingFilter.java @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2018 CyberAgent, Inc. + * + * 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 jp.co.cyberagent.android.gpuimage.filter; + +import android.opengl.GLES20; + +public class GPUImage3x3TextureSamplingFilter extends GPUImageFilter { + public static final String THREE_X_THREE_TEXTURE_SAMPLING_VERTEX_SHADER = "" + + "attribute vec4 position;\n" + + "attribute vec4 inputTextureCoordinate;\n" + + "\n" + + "uniform highp float texelWidth; \n" + + "uniform highp float texelHeight; \n" + + "\n" + + "varying vec2 textureCoordinate;\n" + + "varying vec2 leftTextureCoordinate;\n" + + "varying vec2 rightTextureCoordinate;\n" + + "\n" + + "varying vec2 topTextureCoordinate;\n" + + "varying vec2 topLeftTextureCoordinate;\n" + + "varying vec2 topRightTextureCoordinate;\n" + + "\n" + + "varying vec2 bottomTextureCoordinate;\n" + + "varying vec2 bottomLeftTextureCoordinate;\n" + + "varying vec2 bottomRightTextureCoordinate;\n" + + "\n" + + "void main()\n" + + "{\n" + + " gl_Position = position;\n" + + "\n" + + " vec2 widthStep = vec2(texelWidth, 0.0);\n" + + " vec2 heightStep = vec2(0.0, texelHeight);\n" + + " vec2 widthHeightStep = vec2(texelWidth, texelHeight);\n" + + " vec2 widthNegativeHeightStep = vec2(texelWidth, -texelHeight);\n" + + "\n" + + " textureCoordinate = inputTextureCoordinate.xy;\n" + + " leftTextureCoordinate = inputTextureCoordinate.xy - widthStep;\n" + + " rightTextureCoordinate = inputTextureCoordinate.xy + widthStep;\n" + + "\n" + + " topTextureCoordinate = inputTextureCoordinate.xy - heightStep;\n" + + " topLeftTextureCoordinate = inputTextureCoordinate.xy - widthHeightStep;\n" + + " topRightTextureCoordinate = inputTextureCoordinate.xy + widthNegativeHeightStep;\n" + + "\n" + + " bottomTextureCoordinate = inputTextureCoordinate.xy + heightStep;\n" + + " bottomLeftTextureCoordinate = inputTextureCoordinate.xy - widthNegativeHeightStep;\n" + + " bottomRightTextureCoordinate = inputTextureCoordinate.xy + widthHeightStep;\n" + + "}"; + + private int uniformTexelWidthLocation; + private int uniformTexelHeightLocation; + + private boolean hasOverriddenImageSizeFactor = false; + private float texelWidth; + private float texelHeight; + private float lineSize = 1.0f; + + public GPUImage3x3TextureSamplingFilter() { + this(NO_FILTER_VERTEX_SHADER); + } + + public GPUImage3x3TextureSamplingFilter(final String fragmentShader) { + super(THREE_X_THREE_TEXTURE_SAMPLING_VERTEX_SHADER, fragmentShader); + } + + @Override + public void onInit() { + super.onInit(); + uniformTexelWidthLocation = GLES20.glGetUniformLocation(getProgram(), "texelWidth"); + uniformTexelHeightLocation = GLES20.glGetUniformLocation(getProgram(), "texelHeight"); + } + + @Override + public void onInitialized() { + super.onInitialized(); + if (texelWidth != 0) { + updateTexelValues(); + } + } + + @Override + public void onOutputSizeChanged(final int width, final int height) { + super.onOutputSizeChanged(width, height); + if (!hasOverriddenImageSizeFactor) { + setLineSize(lineSize); + } + } + + public void setTexelWidth(final float texelWidth) { + hasOverriddenImageSizeFactor = true; + this.texelWidth = texelWidth; + setFloat(uniformTexelWidthLocation, texelWidth); + } + + public void setTexelHeight(final float texelHeight) { + hasOverriddenImageSizeFactor = true; + this.texelHeight = texelHeight; + setFloat(uniformTexelHeightLocation, texelHeight); + } + + public void setLineSize(final float size) { + lineSize = size; + texelWidth = size / getOutputWidth(); + texelHeight = size / getOutputHeight(); + updateTexelValues(); + } + + private void updateTexelValues() { + setFloat(uniformTexelWidthLocation, texelWidth); + setFloat(uniformTexelHeightLocation, texelHeight); + } +} diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageAddBlendFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageAddBlendFilter.java similarity index 96% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageAddBlendFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageAddBlendFilter.java index 59dcb3438..750daf91d 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageAddBlendFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageAddBlendFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; public class GPUImageAddBlendFilter extends GPUImageTwoInputFilter { public static final String ADD_BLEND_FRAGMENT_SHADER = "varying highp vec2 textureCoordinate;\n" + diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageAlphaBlendFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageAlphaBlendFilter.java similarity index 94% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageAlphaBlendFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageAlphaBlendFilter.java index 753c24d6c..c59776922 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageAlphaBlendFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageAlphaBlendFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,12 +14,12 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; /** * Mix ranges from 0.0 (only image 1) to 1.0 (only image 2), with 0.5 (half of either) as the normal level */ -public class GPUImageAlphaBlendFilter extends GPUImageMixBlendFilter{ +public class GPUImageAlphaBlendFilter extends GPUImageMixBlendFilter { public static final String ALPHA_BLEND_FRAGMENT_SHADER = "varying highp vec2 textureCoordinate;\n" + " varying highp vec2 textureCoordinate2;\n" + "\n" + diff --git a/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageBilateralBlurFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageBilateralBlurFilter.java new file mode 100644 index 000000000..38015e3d3 --- /dev/null +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageBilateralBlurFilter.java @@ -0,0 +1,153 @@ +/** + * @author wysaid + * @mail admin@wysaid.org + */ + +package jp.co.cyberagent.android.gpuimage.filter; + +import android.opengl.GLES20; + + +public class GPUImageBilateralBlurFilter extends GPUImageFilter { + public static final String BILATERAL_VERTEX_SHADER = "" + + "attribute vec4 position;\n" + + "attribute vec4 inputTextureCoordinate;\n" + + + "const int GAUSSIAN_SAMPLES = 9;\n" + + + "uniform vec2 singleStepOffset;\n" + + + "varying vec2 textureCoordinate;\n" + + "varying vec2 blurCoordinates[GAUSSIAN_SAMPLES];\n" + + + "void main()\n" + + "{\n" + + " gl_Position = position;\n" + + " textureCoordinate = inputTextureCoordinate.xy;\n" + + + " int multiplier = 0;\n" + + " vec2 blurStep;\n" + + + " for (int i = 0; i < GAUSSIAN_SAMPLES; i++)\n" + + " {\n" + + " multiplier = (i - ((GAUSSIAN_SAMPLES - 1) / 2));\n" + + + " blurStep = float(multiplier) * singleStepOffset;\n" + + " blurCoordinates[i] = inputTextureCoordinate.xy + blurStep;\n" + + " }\n" + + "}"; + + public static final String BILATERAL_FRAGMENT_SHADER = "" + + "uniform sampler2D inputImageTexture;\n" + + + " const lowp int GAUSSIAN_SAMPLES = 9;\n" + + + " varying highp vec2 textureCoordinate;\n" + + " varying highp vec2 blurCoordinates[GAUSSIAN_SAMPLES];\n" + + + " uniform mediump float distanceNormalizationFactor;\n" + + + " void main()\n" + + " {\n" + + " lowp vec4 centralColor;\n" + + " lowp float gaussianWeightTotal;\n" + + " lowp vec4 sum;\n" + + " lowp vec4 sampleColor;\n" + + " lowp float distanceFromCentralColor;\n" + + " lowp float gaussianWeight;\n" + + " \n" + + " centralColor = texture2D(inputImageTexture, blurCoordinates[4]);\n" + + " gaussianWeightTotal = 0.18;\n" + + " sum = centralColor * 0.18;\n" + + " \n" + + " sampleColor = texture2D(inputImageTexture, blurCoordinates[0]);\n" + + " distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);\n" + + " gaussianWeight = 0.05 * (1.0 - distanceFromCentralColor);\n" + + " gaussianWeightTotal += gaussianWeight;\n" + + " sum += sampleColor * gaussianWeight;\n" + + + " sampleColor = texture2D(inputImageTexture, blurCoordinates[1]);\n" + + " distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);\n" + + " gaussianWeight = 0.09 * (1.0 - distanceFromCentralColor);\n" + + " gaussianWeightTotal += gaussianWeight;\n" + + " sum += sampleColor * gaussianWeight;\n" + + + " sampleColor = texture2D(inputImageTexture, blurCoordinates[2]);\n" + + " distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);\n" + + " gaussianWeight = 0.12 * (1.0 - distanceFromCentralColor);\n" + + " gaussianWeightTotal += gaussianWeight;\n" + + " sum += sampleColor * gaussianWeight;\n" + + + " sampleColor = texture2D(inputImageTexture, blurCoordinates[3]);\n" + + " distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);\n" + + " gaussianWeight = 0.15 * (1.0 - distanceFromCentralColor);\n" + + " gaussianWeightTotal += gaussianWeight;\n" + + " sum += sampleColor * gaussianWeight;\n" + + + " sampleColor = texture2D(inputImageTexture, blurCoordinates[5]);\n" + + " distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);\n" + + " gaussianWeight = 0.15 * (1.0 - distanceFromCentralColor);\n" + + " gaussianWeightTotal += gaussianWeight;\n" + + " sum += sampleColor * gaussianWeight;\n" + + + " sampleColor = texture2D(inputImageTexture, blurCoordinates[6]);\n" + + " distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);\n" + + " gaussianWeight = 0.12 * (1.0 - distanceFromCentralColor);\n" + + " gaussianWeightTotal += gaussianWeight;\n" + + " sum += sampleColor * gaussianWeight;\n" + + + " sampleColor = texture2D(inputImageTexture, blurCoordinates[7]);\n" + + " distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);\n" + + " gaussianWeight = 0.09 * (1.0 - distanceFromCentralColor);\n" + + " gaussianWeightTotal += gaussianWeight;\n" + + " sum += sampleColor * gaussianWeight;\n" + + + " sampleColor = texture2D(inputImageTexture, blurCoordinates[8]);\n" + + " distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);\n" + + " gaussianWeight = 0.05 * (1.0 - distanceFromCentralColor);\n" + + " gaussianWeightTotal += gaussianWeight;\n" + + " sum += sampleColor * gaussianWeight;\n" + + " gl_FragColor = sum / gaussianWeightTotal;\n" + + " }"; + + private float distanceNormalizationFactor; + private int disFactorLocation; + private int singleStepOffsetLocation; + + public GPUImageBilateralBlurFilter() { + this(8.0f); + } + + public GPUImageBilateralBlurFilter(final float distanceNormalizationFactor) { + super(BILATERAL_VERTEX_SHADER, BILATERAL_FRAGMENT_SHADER); + this.distanceNormalizationFactor = distanceNormalizationFactor; + } + + @Override + public void onInit() { + super.onInit(); + disFactorLocation = GLES20.glGetUniformLocation(getProgram(), "distanceNormalizationFactor"); + singleStepOffsetLocation = GLES20.glGetUniformLocation(getProgram(), "singleStepOffset"); + } + + @Override + public void onInitialized() { + super.onInitialized(); + setDistanceNormalizationFactor(distanceNormalizationFactor); + } + + public void setDistanceNormalizationFactor(final float newValue) { + distanceNormalizationFactor = newValue; + setFloat(disFactorLocation, newValue); + } + + private void setTexelSize(final float w, final float h) { + setFloatVec2(singleStepOffsetLocation, new float[]{1.0f / w, 1.0f / h}); + } + + @Override + public void onOutputSizeChanged(final int width, final int height) { + super.onOutputSizeChanged(width, height); + setTexelSize(width, height); + } +} diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageBoxBlurFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageBoxBlurFilter.java similarity index 94% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageBoxBlurFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageBoxBlurFilter.java index 4e681b3c5..2c4002922 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageBoxBlurFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageBoxBlurFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,11 +14,11 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; /** * A hardware-accelerated 9-hit box blur of an image - * + *

* scaling: for the size of the applied blur, default of 1.0 */ public class GPUImageBoxBlurFilter extends GPUImageTwoPassTextureSamplingFilter { @@ -71,7 +71,7 @@ public class GPUImageBoxBlurFilter extends GPUImageTwoPassTextureSamplingFilter "gl_FragColor = fragmentColor;\n" + "}\n"; - private float blurSize = 1f; + private float blurSize; /** * Construct new BoxBlurFilter with default blur size of 1.0. @@ -86,6 +86,12 @@ public GPUImageBoxBlurFilter(float blurSize) { this.blurSize = blurSize; } + @Override + public void onInitialized() { + super.onInitialized(); + setBlurSize(blurSize); + } + /** * A scaling for the size of the applied blur, default of 1.0 * diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageBrightnessFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageBrightnessFilter.java similarity index 80% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageBrightnessFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageBrightnessFilter.java index e528ee879..fe8f1028f 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageBrightnessFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageBrightnessFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; import android.opengl.GLES20; @@ -35,8 +35,8 @@ public class GPUImageBrightnessFilter extends GPUImageFilter { " gl_FragColor = vec4((textureColor.rgb + vec3(brightness)), textureColor.w);\n" + " }"; - private int mBrightnessLocation; - private float mBrightness; + private int brightnessLocation; + private float brightness; public GPUImageBrightnessFilter() { this(0.0f); @@ -44,23 +44,23 @@ public GPUImageBrightnessFilter() { public GPUImageBrightnessFilter(final float brightness) { super(NO_FILTER_VERTEX_SHADER, BRIGHTNESS_FRAGMENT_SHADER); - mBrightness = brightness; + this.brightness = brightness; } @Override public void onInit() { super.onInit(); - mBrightnessLocation = GLES20.glGetUniformLocation(getProgram(), "brightness"); + brightnessLocation = GLES20.glGetUniformLocation(getProgram(), "brightness"); } @Override public void onInitialized() { super.onInitialized(); - setBrightness(mBrightness); + setBrightness(brightness); } public void setBrightness(final float brightness) { - mBrightness = brightness; - setFloat(mBrightnessLocation, mBrightness); + this.brightness = brightness; + setFloat(brightnessLocation, this.brightness); } } diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageBulgeDistortionFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageBulgeDistortionFilter.java similarity index 72% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageBulgeDistortionFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageBulgeDistortionFilter.java index af49beddf..fe70c1fea 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageBulgeDistortionFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageBulgeDistortionFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; import android.graphics.PointF; import android.opengl.GLES20; @@ -49,14 +49,14 @@ public class GPUImageBulgeDistortionFilter extends GPUImageFilter { "gl_FragColor = texture2D(inputImageTexture, textureCoordinateToUse ); \n" + "}\n"; - private float mScale; - private int mScaleLocation; - private float mRadius; - private int mRadiusLocation; - private PointF mCenter; - private int mCenterLocation; - private float mAspectRatio; - private int mAspectRatioLocation; + private float scale; + private int scaleLocation; + private float radius; + private int radiusLocation; + private PointF center; + private int centerLocation; + private float aspectRatio; + private int aspectRatioLocation; public GPUImageBulgeDistortionFilter() { this(0.25f, 0.5f, new PointF(0.5f, 0.5f)); @@ -64,38 +64,39 @@ public GPUImageBulgeDistortionFilter() { public GPUImageBulgeDistortionFilter(float radius, float scale, PointF center) { super(NO_FILTER_VERTEX_SHADER, BULGE_FRAGMENT_SHADER); - mRadius = radius; - mScale = scale; - mCenter = center; + this.radius = radius; + this.scale = scale; + this.center = center; } @Override public void onInit() { super.onInit(); - mScaleLocation = GLES20.glGetUniformLocation(getProgram(), "scale"); - mRadiusLocation = GLES20.glGetUniformLocation(getProgram(), "radius"); - mCenterLocation = GLES20.glGetUniformLocation(getProgram(), "center"); - mAspectRatioLocation = GLES20.glGetUniformLocation(getProgram(), "aspectRatio"); + scaleLocation = GLES20.glGetUniformLocation(getProgram(), "scale"); + radiusLocation = GLES20.glGetUniformLocation(getProgram(), "radius"); + centerLocation = GLES20.glGetUniformLocation(getProgram(), "center"); + aspectRatioLocation = GLES20.glGetUniformLocation(getProgram(), "aspectRatio"); } @Override public void onInitialized() { super.onInitialized(); - setRadius(mRadius); - setScale(mScale); - setCenter(mCenter); + setAspectRatio(aspectRatio); + setRadius(radius); + setScale(scale); + setCenter(center); } @Override public void onOutputSizeChanged(int width, int height) { - mAspectRatio = (float) height / width; - setAspectRatio(mAspectRatio); + aspectRatio = (float) height / width; + setAspectRatio(aspectRatio); super.onOutputSizeChanged(width, height); } private void setAspectRatio(float aspectRatio) { - mAspectRatio = aspectRatio; - setFloat(mAspectRatioLocation, aspectRatio); + this.aspectRatio = aspectRatio; + setFloat(aspectRatioLocation, aspectRatio); } /** @@ -104,8 +105,8 @@ private void setAspectRatio(float aspectRatio) { * @param radius from 0.0 to 1.0, default 0.25 */ public void setRadius(float radius) { - mRadius = radius; - setFloat(mRadiusLocation, radius); + this.radius = radius; + setFloat(radiusLocation, radius); } /** @@ -114,8 +115,8 @@ public void setRadius(float radius) { * @param scale from -1.0 to 1.0, default 0.5 */ public void setScale(float scale) { - mScale = scale; - setFloat(mScaleLocation, scale); + this.scale = scale; + setFloat(scaleLocation, scale); } /** @@ -124,7 +125,7 @@ public void setScale(float scale) { * @param center default (0.5, 0.5) */ public void setCenter(PointF center) { - mCenter = center; - setPoint(mCenterLocation, center); + this.center = center; + setPoint(centerLocation, center); } } diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageCGAColorspaceFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageCGAColorspaceFilter.java similarity index 97% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageCGAColorspaceFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageCGAColorspaceFilter.java index 525859569..7ab1a7d8d 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageCGAColorspaceFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageCGAColorspaceFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; public class GPUImageCGAColorspaceFilter extends GPUImageFilter { public static final String CGACOLORSPACE_FRAGMENT_SHADER = "" + diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageChromaKeyBlendFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageChromaKeyBlendFilter.java similarity index 69% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageChromaKeyBlendFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageChromaKeyBlendFilter.java index 7957b05a2..18c78436a 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageChromaKeyBlendFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageChromaKeyBlendFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; import android.opengl.GLES20; @@ -50,12 +50,12 @@ public class GPUImageChromaKeyBlendFilter extends GPUImageTwoInputFilter { " gl_FragColor = mix(textureColor, textureColor2, blendValue);\n" + " }"; - private int mThresholdSensitivityLocation; - private int mSmoothingLocation; - private int mColorToReplaceLocation; - private float mSmoothing = 0.1f; - private float mThresholdSensitivity = 0.3f; - private float[] mColorToReplace = new float[]{0.0f, 1.0f, 0.0f}; + private int thresholdSensitivityLocation; + private int smoothingLocation; + private int colorToReplaceLocation; + private float thresholdSensitivity = 0.4f; + private float smoothing = 0.1f; + private float[] colorToReplace = new float[]{0.0f, 1.0f, 0.0f}; public GPUImageChromaKeyBlendFilter() { super(CHROMA_KEY_BLEND_FRAGMENT_SHADER); @@ -65,17 +65,17 @@ public GPUImageChromaKeyBlendFilter() { @Override public void onInit() { super.onInit(); - mThresholdSensitivityLocation = GLES20.glGetUniformLocation(getProgram(), "thresholdSensitivity"); - mSmoothingLocation = GLES20.glGetUniformLocation(getProgram(), "smoothing"); - mColorToReplaceLocation = GLES20.glGetUniformLocation(getProgram(), "colorToReplace"); + thresholdSensitivityLocation = GLES20.glGetUniformLocation(getProgram(), "thresholdSensitivity"); + smoothingLocation = GLES20.glGetUniformLocation(getProgram(), "smoothing"); + colorToReplaceLocation = GLES20.glGetUniformLocation(getProgram(), "colorToReplace"); } @Override public void onInitialized() { super.onInitialized(); - setSmoothing(mSmoothing); - setThresholdSensitivity(mThresholdSensitivity); - setColorToReplace(mColorToReplace[0], mColorToReplace[1], mColorToReplace[2]); + setSmoothing(smoothing); + setThresholdSensitivity(thresholdSensitivity); + setColorToReplace(colorToReplace[0], colorToReplace[1], colorToReplace[2]); } /** @@ -83,8 +83,8 @@ public void onInitialized() { * The default value is 0.1 */ public void setSmoothing(final float smoothing) { - mSmoothing = smoothing; - setFloat(mSmoothingLocation, mSmoothing); + this.smoothing = smoothing; + setFloat(smoothingLocation, this.smoothing); } /** @@ -92,19 +92,20 @@ public void setSmoothing(final float smoothing) { * The default value is 0.3 */ public void setThresholdSensitivity(final float thresholdSensitivity) { - mThresholdSensitivity = thresholdSensitivity; - setFloat(mThresholdSensitivityLocation, mThresholdSensitivity); + this.thresholdSensitivity = thresholdSensitivity; + setFloat(thresholdSensitivityLocation, this.thresholdSensitivity); } - /** The color to be replaced is specified using individual red, green, and blue components (normalized to 1.0). + /** + * The color to be replaced is specified using individual red, green, and blue components (normalized to 1.0). * The default is green: (0.0, 1.0, 0.0). * - * @param redComponent Red component of color to be replaced + * @param redComponent Red component of color to be replaced * @param greenComponent Green component of color to be replaced - * @param blueComponent Blue component of color to be replaced + * @param blueComponent Blue component of color to be replaced */ public void setColorToReplace(float redComponent, float greenComponent, float blueComponent) { - mColorToReplace = new float[]{redComponent, greenComponent, blueComponent}; - setFloatVec3(mColorToReplaceLocation, mColorToReplace); + colorToReplace = new float[]{redComponent, greenComponent, blueComponent}; + setFloatVec3(colorToReplaceLocation, colorToReplace); } } diff --git a/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageColorBalanceFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageColorBalanceFilter.java new file mode 100644 index 000000000..ef9337dcb --- /dev/null +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageColorBalanceFilter.java @@ -0,0 +1,197 @@ +package jp.co.cyberagent.android.gpuimage.filter; + +import android.opengl.GLES20; + +/** + * Created by edward_chiang on 13/10/16. + */ +public class GPUImageColorBalanceFilter extends GPUImageFilter { + + public static final String GPU_IMAGE_COLOR_BALANCE_FRAGMENT_SHADER = "" + + "varying highp vec2 textureCoordinate;\n" + + "uniform sampler2D inputImageTexture;\n" + + "uniform lowp vec3 shadowsShift;\n" + + "uniform lowp vec3 midtonesShift;\n" + + "uniform lowp vec3 highlightsShift;\n" + + "uniform int preserveLuminosity;\n" + + "lowp vec3 RGBToHSL(lowp vec3 color)\n" + + + "{\n" + + "lowp vec3 hsl; // init to 0 to avoid warnings ? (and reverse if + remove first part)\n" + + + "lowp float fmin = min(min(color.r, color.g), color.b); //Min. value of RGB\n" + + "lowp float fmax = max(max(color.r, color.g), color.b); //Max. value of RGB\n" + + "lowp float delta = fmax - fmin; //Delta RGB value\n" + + + "hsl.z = (fmax + fmin) / 2.0; // Luminance\n" + + + "if (delta == 0.0) //This is a gray, no chroma...\n" + + "{\n" + + " hsl.x = 0.0; // Hue\n" + + " hsl.y = 0.0; // Saturation\n" + + "}\n" + + "else //Chromatic data...\n" + + "{\n" + + " if (hsl.z < 0.5)\n" + + " hsl.y = delta / (fmax + fmin); // Saturation\n" + + " else\n" + + " hsl.y = delta / (2.0 - fmax - fmin); // Saturation\n" + + "\n" + + " lowp float deltaR = (((fmax - color.r) / 6.0) + (delta / 2.0)) / delta;\n" + + " lowp float deltaG = (((fmax - color.g) / 6.0) + (delta / 2.0)) / delta;\n" + + " lowp float deltaB = (((fmax - color.b) / 6.0) + (delta / 2.0)) / delta;\n" + + "\n" + + " if (color.r == fmax )\n" + + " hsl.x = deltaB - deltaG; // Hue\n" + + " else if (color.g == fmax)\n" + + " hsl.x = (1.0 / 3.0) + deltaR - deltaB; // Hue\n" + + " else if (color.b == fmax)\n" + + " hsl.x = (2.0 / 3.0) + deltaG - deltaR; // Hue\n" + + + " if (hsl.x < 0.0)\n" + + " hsl.x += 1.0; // Hue\n" + + " else if (hsl.x > 1.0)\n" + + " hsl.x -= 1.0; // Hue\n" + + "}\n" + + "\n" + + "return hsl;\n" + + "}\n" + + + "lowp float HueToRGB(lowp float f1, lowp float f2, lowp float hue)\n" + + "{\n" + + " if (hue < 0.0)\n" + + " hue += 1.0;\n" + + " else if (hue > 1.0)\n" + + " hue -= 1.0;\n" + + " lowp float res;\n" + + " if ((6.0 * hue) < 1.0)\n" + + " res = f1 + (f2 - f1) * 6.0 * hue;\n" + + " else if ((2.0 * hue) < 1.0)\n" + + " res = f2;\n" + + " else if ((3.0 * hue) < 2.0)\n" + + " res = f1 + (f2 - f1) * ((2.0 / 3.0) - hue) * 6.0;\n" + + " else\n" + + " res = f1;\n" + + " return res;\n" + + "}\n" + + + "lowp vec3 HSLToRGB(lowp vec3 hsl)\n" + + "{\n" + + " lowp vec3 rgb;\n" + + + " if (hsl.y == 0.0)\n" + + " rgb = vec3(hsl.z); // Luminance\n" + + " else\n" + + " {\n" + + " lowp float f2;\n" + + + " if (hsl.z < 0.5)\n" + + " f2 = hsl.z * (1.0 + hsl.y);\n" + + " else\n" + + " f2 = (hsl.z + hsl.y) - (hsl.y * hsl.z);\n" + + + " lowp float f1 = 2.0 * hsl.z - f2;\n" + + + " rgb.r = HueToRGB(f1, f2, hsl.x + (1.0/3.0));\n" + + " rgb.g = HueToRGB(f1, f2, hsl.x);\n" + + " rgb.b= HueToRGB(f1, f2, hsl.x - (1.0/3.0));\n" + + " }\n" + + + " return rgb;\n " + + "}\n" + + + "lowp float RGBToL(lowp vec3 color)\n" + + "{\n" + + " lowp float fmin = min(min(color.r, color.g), color.b); //Min. value of RGB\n" + + " lowp float fmax = max(max(color.r, color.g), color.b); //Max. value of RGB\n" + + + " return (fmax + fmin) / 2.0; // Luminance\n" + + "}\n" + + + "void main()\n" + + "{\n" + + " lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);\n" + + + " // Alternative way:\n" + + " //lowp vec3 lightness = RGBToL(textureColor.rgb);\n" + + " lowp vec3 lightness = textureColor.rgb;\n" + + + " const lowp float a = 0.25;\n" + + " const lowp float b = 0.333;\n" + + " const lowp float scale = 0.7;\n" + + + " lowp vec3 shadows = shadowsShift * (clamp((lightness - b) / -a + 0.5, 0.0, 1.0) * scale);\n" + + " lowp vec3 midtones = midtonesShift * (clamp((lightness - b) / a + 0.5, 0.0, 1.0) *\n" + + " clamp((lightness + b - 1.0) / -a + 0.5, 0.0, 1.0) * scale);\n" + + " lowp vec3 highlights = highlightsShift * (clamp((lightness + b - 1.0) / a + 0.5, 0.0, 1.0) * scale);\n" + + + " mediump vec3 newColor = textureColor.rgb + shadows + midtones + highlights;\n" + + " newColor = clamp(newColor, 0.0, 1.0);\n " + + + " if (preserveLuminosity != 0) {\n " + + " lowp vec3 newHSL = RGBToHSL(newColor);\n" + + " lowp float oldLum = RGBToL(textureColor.rgb);\n" + + " textureColor.rgb = HSLToRGB(vec3(newHSL.x, newHSL.y, oldLum));\n" + + " gl_FragColor = textureColor;\n" + + " } else {\n" + + " gl_FragColor = vec4(newColor.rgb, textureColor.w);\n" + + " }\n" + + "}\n"; + + private int shadowsLocation; + private int midtonesLocation; + private int highlightsLocation; + private int preserveLuminosityLocation; + + private float[] showdows; + private float[] midtones; + private float[] highlights; + private boolean preserveLuminosity; + + + public GPUImageColorBalanceFilter() { + super(NO_FILTER_VERTEX_SHADER, GPU_IMAGE_COLOR_BALANCE_FRAGMENT_SHADER); + this.showdows = new float[]{0.0f, 0.0f, 0.0f}; + this.midtones = new float[]{0.0f, 0.0f, 0.0f}; + this.highlights = new float[]{0.0f, 0.0f, 0.0f}; + this.preserveLuminosity = true; + } + + @Override + public void onInit() { + super.onInit(); + shadowsLocation = GLES20.glGetUniformLocation(getProgram(), "shadowsShift"); + midtonesLocation = GLES20.glGetUniformLocation(getProgram(), "midtonesShift"); + highlightsLocation = GLES20.glGetUniformLocation(getProgram(), "highlightsShift"); + preserveLuminosityLocation = GLES20.glGetUniformLocation(getProgram(), "preserveLuminosity"); + } + + @Override + public void onInitialized() { + super.onInitialized(); + setMidtones(midtones); + setShowdows(showdows); + setHighlights(highlights); + setPreserveLuminosity(preserveLuminosity); + } + + public void setShowdows(float[] showdows) { + this.showdows = showdows; + setFloatVec3(shadowsLocation, showdows); + } + + public void setMidtones(float[] midtones) { + this.midtones = midtones; + setFloatVec3(midtonesLocation, midtones); + } + + public void setHighlights(float[] highlights) { + this.highlights = highlights; + setFloatVec3(highlightsLocation, highlights); + } + + public void setPreserveLuminosity(boolean preserveLuminosity) { + this.preserveLuminosity = preserveLuminosity; + setInteger(preserveLuminosityLocation, preserveLuminosity ? 1 : 0); + } +} diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageColorBlendFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageColorBlendFilter.java similarity index 96% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageColorBlendFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageColorBlendFilter.java index 0f5de140d..e29b7381e 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageColorBlendFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageColorBlendFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; public class GPUImageColorBlendFilter extends GPUImageTwoInputFilter { public static final String COLOR_BLEND_FRAGMENT_SHADER = "varying highp vec2 textureCoordinate;\n" + diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageColorBurnBlendFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageColorBurnBlendFilter.java similarity index 94% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageColorBurnBlendFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageColorBurnBlendFilter.java index e3b5c42a5..a3ff750ab 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageColorBurnBlendFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageColorBurnBlendFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; public class GPUImageColorBurnBlendFilter extends GPUImageTwoInputFilter { public static final String COLOR_BURN_BLEND_FRAGMENT_SHADER = "varying highp vec2 textureCoordinate;\n" + diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageColorDodgeBlendFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageColorDodgeBlendFilter.java similarity index 96% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageColorDodgeBlendFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageColorDodgeBlendFilter.java index 702a3a985..4609c6cbb 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageColorDodgeBlendFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageColorDodgeBlendFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; public class GPUImageColorDodgeBlendFilter extends GPUImageTwoInputFilter { public static final String COLOR_DODGE_BLEND_FRAGMENT_SHADER = "precision mediump float;\n" + diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageColorInvertFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageColorInvertFilter.java similarity index 93% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageColorInvertFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageColorInvertFilter.java index 2d8df9b94..7154ca691 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageColorInvertFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageColorInvertFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; /** * Invert all the colors in the image. diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageColorMatrixFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageColorMatrixFilter.java similarity index 73% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageColorMatrixFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageColorMatrixFilter.java index 59203c4d2..a3e8ddd4e 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageColorMatrixFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageColorMatrixFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; import android.opengl.GLES20; @@ -38,13 +38,13 @@ public class GPUImageColorMatrixFilter extends GPUImageFilter { " gl_FragColor = (intensity * outputColor) + ((1.0 - intensity) * textureColor);\n" + "}"; - private float mIntensity; - private float[] mColorMatrix; - private int mColorMatrixLocation; - private int mIntensityLocation; + private float intensity; + private float[] colorMatrix; + private int colorMatrixLocation; + private int intensityLocation; public GPUImageColorMatrixFilter() { - this(1.0f, new float[] { + this(1.0f, new float[]{ 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, @@ -54,31 +54,31 @@ public GPUImageColorMatrixFilter() { public GPUImageColorMatrixFilter(final float intensity, final float[] colorMatrix) { super(NO_FILTER_VERTEX_SHADER, COLOR_MATRIX_FRAGMENT_SHADER); - mIntensity = intensity; - mColorMatrix = colorMatrix; + this.intensity = intensity; + this.colorMatrix = colorMatrix; } @Override public void onInit() { super.onInit(); - mColorMatrixLocation = GLES20.glGetUniformLocation(getProgram(), "colorMatrix"); - mIntensityLocation = GLES20.glGetUniformLocation(getProgram(), "intensity"); + colorMatrixLocation = GLES20.glGetUniformLocation(getProgram(), "colorMatrix"); + intensityLocation = GLES20.glGetUniformLocation(getProgram(), "intensity"); } @Override public void onInitialized() { super.onInitialized(); - setIntensity(mIntensity); - setColorMatrix(mColorMatrix); + setIntensity(intensity); + setColorMatrix(colorMatrix); } public void setIntensity(final float intensity) { - mIntensity = intensity; - setFloat(mIntensityLocation, intensity); + this.intensity = intensity; + setFloat(intensityLocation, intensity); } public void setColorMatrix(final float[] colorMatrix) { - mColorMatrix = colorMatrix; - setUniformMatrix4f(mColorMatrixLocation, colorMatrix); + this.colorMatrix = colorMatrix; + setUniformMatrix4f(colorMatrixLocation, colorMatrix); } } diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageContrastFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageContrastFilter.java similarity index 65% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageContrastFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageContrastFilter.java index 1d2b9107a..bd890f73f 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageContrastFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageContrastFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; import android.opengl.GLES20; @@ -25,44 +25,44 @@ */ public class GPUImageContrastFilter extends GPUImageFilter { public static final String CONTRAST_FRAGMENT_SHADER = "" + - "varying highp vec2 textureCoordinate;\n" + - " \n" + - " uniform sampler2D inputImageTexture;\n" + - " uniform lowp float contrast;\n" + - " \n" + - " void main()\n" + - " {\n" + - " lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);\n" + - " \n" + - " gl_FragColor = vec4(((textureColor.rgb - vec3(0.5)) * contrast + vec3(0.5)), textureColor.w);\n" + + "varying highp vec2 textureCoordinate;\n" + + " \n" + + " uniform sampler2D inputImageTexture;\n" + + " uniform lowp float contrast;\n" + + " \n" + + " void main()\n" + + " {\n" + + " lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);\n" + + " \n" + + " gl_FragColor = vec4(((textureColor.rgb - vec3(0.5)) * contrast + vec3(0.5)), textureColor.w);\n" + " }"; - private int mContrastLocation; - private float mContrast; + private int contrastLocation; + private float contrast; public GPUImageContrastFilter() { this(1.2f); } - + public GPUImageContrastFilter(float contrast) { super(NO_FILTER_VERTEX_SHADER, CONTRAST_FRAGMENT_SHADER); - mContrast = contrast; + this.contrast = contrast; } @Override public void onInit() { super.onInit(); - mContrastLocation = GLES20.glGetUniformLocation(getProgram(), "contrast"); + contrastLocation = GLES20.glGetUniformLocation(getProgram(), "contrast"); } @Override public void onInitialized() { super.onInitialized(); - setContrast(mContrast); + setContrast(contrast); } public void setContrast(final float contrast) { - mContrast = contrast; - setFloat(mContrastLocation, mContrast); + this.contrast = contrast; + setFloat(contrastLocation, this.contrast); } } diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageCrosshatchFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageCrosshatchFilter.java similarity index 82% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageCrosshatchFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageCrosshatchFilter.java index 04a3d4c74..4fceb3284 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageCrosshatchFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageCrosshatchFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; import android.opengl.GLES20; @@ -64,10 +64,10 @@ public class GPUImageCrosshatchFilter extends GPUImageFilter { "gl_FragColor = colorToDisplay;\n" + "}\n"; - private float mCrossHatchSpacing; - private int mCrossHatchSpacingLocation; - private float mLineWidth; - private int mLineWidthLocation; + private float crossHatchSpacing; + private int crossHatchSpacingLocation; + private float lineWidth; + private int lineWidthLocation; /** * Using default values of crossHatchSpacing: 0.03f and lineWidth: 0.003f. @@ -78,22 +78,22 @@ public GPUImageCrosshatchFilter() { public GPUImageCrosshatchFilter(float crossHatchSpacing, float lineWidth) { super(NO_FILTER_VERTEX_SHADER, CROSSHATCH_FRAGMENT_SHADER); - mCrossHatchSpacing = crossHatchSpacing; - mLineWidth = lineWidth; + this.crossHatchSpacing = crossHatchSpacing; + this.lineWidth = lineWidth; } @Override public void onInit() { super.onInit(); - mCrossHatchSpacingLocation = GLES20.glGetUniformLocation(getProgram(), "crossHatchSpacing"); - mLineWidthLocation = GLES20.glGetUniformLocation(getProgram(), "lineWidth"); + crossHatchSpacingLocation = GLES20.glGetUniformLocation(getProgram(), "crossHatchSpacing"); + lineWidthLocation = GLES20.glGetUniformLocation(getProgram(), "lineWidth"); } @Override public void onInitialized() { super.onInitialized(); - setCrossHatchSpacing(mCrossHatchSpacing); - setLineWidth(mLineWidth); + setCrossHatchSpacing(crossHatchSpacing); + setLineWidth(lineWidth); } /** @@ -110,12 +110,12 @@ public void setCrossHatchSpacing(final float crossHatchSpacing) { } if (crossHatchSpacing < singlePixelSpacing) { - mCrossHatchSpacing = singlePixelSpacing; + this.crossHatchSpacing = singlePixelSpacing; } else { - mCrossHatchSpacing = crossHatchSpacing; + this.crossHatchSpacing = crossHatchSpacing; } - setFloat(mCrossHatchSpacingLocation, mCrossHatchSpacing); + setFloat(crossHatchSpacingLocation, this.crossHatchSpacing); } /** @@ -124,7 +124,7 @@ public void setCrossHatchSpacing(final float crossHatchSpacing) { * @param lineWidth default 0.003 */ public void setLineWidth(final float lineWidth) { - mLineWidth = lineWidth; - setFloat(mLineWidthLocation, mLineWidth); + this.lineWidth = lineWidth; + setFloat(lineWidthLocation, this.lineWidth); } } diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageDarkenBlendFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageDarkenBlendFilter.java similarity index 94% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageDarkenBlendFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageDarkenBlendFilter.java index 385e8e3a0..599eaf70a 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageDarkenBlendFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageDarkenBlendFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; public class GPUImageDarkenBlendFilter extends GPUImageTwoInputFilter { public static final String DARKEN_BLEND_FRAGMENT_SHADER = "varying highp vec2 textureCoordinate;\n" + diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageDifferenceBlendFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageDifferenceBlendFilter.java similarity index 94% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageDifferenceBlendFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageDifferenceBlendFilter.java index 1a32cd0cf..6ceabe1b4 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageDifferenceBlendFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageDifferenceBlendFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; public class GPUImageDifferenceBlendFilter extends GPUImageTwoInputFilter { public static final String DIFFERENCE_BLEND_FRAGMENT_SHADER = "varying highp vec2 textureCoordinate;\n" + diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageDilationFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageDilationFilter.java similarity index 99% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageDilationFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageDilationFilter.java index f6ce4e2f5..06101a082 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageDilationFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageDilationFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; /** * For each pixel, this sets it to the maximum value of the red channel in a rectangular neighborhood extending diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageDirectionalSobelEdgeDetectionFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageDirectionalSobelEdgeDetectionFilter.java similarity index 58% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageDirectionalSobelEdgeDetectionFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageDirectionalSobelEdgeDetectionFilter.java index a5884a121..eb71c7f19 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageDirectionalSobelEdgeDetectionFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageDirectionalSobelEdgeDetectionFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,48 +14,48 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; public class GPUImageDirectionalSobelEdgeDetectionFilter extends GPUImage3x3TextureSamplingFilter { public static final String DIRECTIONAL_SOBEL_EDGE_DETECTION_FRAGMENT_SHADER = "" + - "precision mediump float;\n" + + "precision mediump float;\n" + "\n" + - "varying vec2 textureCoordinate;\n" + - "varying vec2 leftTextureCoordinate;\n" + - "varying vec2 rightTextureCoordinate;\n" + + "varying vec2 textureCoordinate;\n" + + "varying vec2 leftTextureCoordinate;\n" + + "varying vec2 rightTextureCoordinate;\n" + "\n" + - "varying vec2 topTextureCoordinate;\n" + - "varying vec2 topLeftTextureCoordinate;\n" + - "varying vec2 topRightTextureCoordinate;\n" + - "\n" + - "varying vec2 bottomTextureCoordinate;\n" + - "varying vec2 bottomLeftTextureCoordinate;\n" + - "varying vec2 bottomRightTextureCoordinate;\n" + - "\n" + - "uniform sampler2D inputImageTexture;\n" + - "\n" + - "void main()\n" + - "{\n" + - " float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r;\n" + - " float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r;\n" + - " float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r;\n" + - " float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r;\n" + - " float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r;\n" + - " float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r;\n" + - " float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r;\n" + - " float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r;\n" + - "\n" + - " vec2 gradientDirection;\n" + - " gradientDirection.x = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomRightIntensity + 2.0 * rightIntensity + topRightIntensity;\n" + - " gradientDirection.y = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + bottomLeftIntensity + 2.0 * bottomIntensity + bottomRightIntensity;\n" + - "\n" + - " float gradientMagnitude = length(gradientDirection);\n" + - " vec2 normalizedDirection = normalize(gradientDirection);\n" + - " normalizedDirection = sign(normalizedDirection) * floor(abs(normalizedDirection) + 0.617316); // Offset by 1-sin(pi/8) to set to 0 if near axis, 1 if away\n" + - " normalizedDirection = (normalizedDirection + 1.0) * 0.5; // Place -1.0 - 1.0 within 0 - 1.0\n" + - "\n" + - " gl_FragColor = vec4(gradientMagnitude, normalizedDirection.x, normalizedDirection.y, 1.0);\n" + + "varying vec2 topTextureCoordinate;\n" + + "varying vec2 topLeftTextureCoordinate;\n" + + "varying vec2 topRightTextureCoordinate;\n" + + "\n" + + "varying vec2 bottomTextureCoordinate;\n" + + "varying vec2 bottomLeftTextureCoordinate;\n" + + "varying vec2 bottomRightTextureCoordinate;\n" + + "\n" + + "uniform sampler2D inputImageTexture;\n" + + "\n" + + "void main()\n" + + "{\n" + + " float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r;\n" + + " float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r;\n" + + " float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r;\n" + + " float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r;\n" + + " float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r;\n" + + " float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r;\n" + + " float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r;\n" + + " float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r;\n" + + "\n" + + " vec2 gradientDirection;\n" + + " gradientDirection.x = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomRightIntensity + 2.0 * rightIntensity + topRightIntensity;\n" + + " gradientDirection.y = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + bottomLeftIntensity + 2.0 * bottomIntensity + bottomRightIntensity;\n" + + "\n" + + " float gradientMagnitude = length(gradientDirection);\n" + + " vec2 normalizedDirection = normalize(gradientDirection);\n" + + " normalizedDirection = sign(normalizedDirection) * floor(abs(normalizedDirection) + 0.617316); // Offset by 1-sin(pi/8) to set to 0 if near axis, 1 if away\n" + + " normalizedDirection = (normalizedDirection + 1.0) * 0.5; // Place -1.0 - 1.0 within 0 - 1.0\n" + + "\n" + + " gl_FragColor = vec4(gradientMagnitude, normalizedDirection.x, normalizedDirection.y, 1.0);\n" + "}"; public GPUImageDirectionalSobelEdgeDetectionFilter() { diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageDissolveBlendFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageDissolveBlendFilter.java similarity index 93% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageDissolveBlendFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageDissolveBlendFilter.java index cd2880a60..7ae8dee31 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageDissolveBlendFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageDissolveBlendFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,14 +14,12 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; - -import android.opengl.GLES20; +package jp.co.cyberagent.android.gpuimage.filter; /** * Mix ranges from 0.0 (only image 1) to 1.0 (only image 2), with 0.5 (half of either) as the normal level */ -public class GPUImageDissolveBlendFilter extends GPUImageMixBlendFilter{ +public class GPUImageDissolveBlendFilter extends GPUImageMixBlendFilter { public static final String DISSOLVE_BLEND_FRAGMENT_SHADER = "varying highp vec2 textureCoordinate;\n" + " varying highp vec2 textureCoordinate2;\n" + "\n" + diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageDivideBlendFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageDivideBlendFilter.java similarity index 96% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageDivideBlendFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageDivideBlendFilter.java index 179cd4eea..e0b48dba0 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageDivideBlendFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageDivideBlendFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; public class GPUImageDivideBlendFilter extends GPUImageTwoInputFilter { public static final String DIVIDE_BLEND_FRAGMENT_SHADER = "varying highp vec2 textureCoordinate;\n" + diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageEmbossFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageEmbossFilter.java similarity index 76% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageEmbossFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageEmbossFilter.java index f4cbdef77..5af70fc2e 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageEmbossFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageEmbossFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; /** * Applies an emboss effect to the image.
@@ -22,7 +22,7 @@ * Intensity ranges from 0.0 to 4.0, with 1.0 as the normal level */ public class GPUImageEmbossFilter extends GPUImage3x3ConvolutionFilter { - private float mIntensity; + private float intensity; public GPUImageEmbossFilter() { this(1.0f); @@ -30,18 +30,23 @@ public GPUImageEmbossFilter() { public GPUImageEmbossFilter(final float intensity) { super(); - mIntensity = intensity; + this.intensity = intensity; } @Override public void onInit() { super.onInit(); - setIntensity(mIntensity); + } + + @Override + public void onInitialized() { + super.onInitialized(); + setIntensity(intensity); } public void setIntensity(final float intensity) { - mIntensity = intensity; - setConvolutionKernel(new float[] { + this.intensity = intensity; + setConvolutionKernel(new float[]{ intensity * (-2.0f), -intensity, 0.0f, -intensity, 1.0f, intensity, 0.0f, intensity, intensity * 2.0f, @@ -49,6 +54,6 @@ public void setIntensity(final float intensity) { } public float getIntensity() { - return mIntensity; + return intensity; } } diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageExclusionBlendFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageExclusionBlendFilter.java similarity index 94% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageExclusionBlendFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageExclusionBlendFilter.java index dcfc9346f..20bb2a054 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageExclusionBlendFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageExclusionBlendFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; public class GPUImageExclusionBlendFilter extends GPUImageTwoInputFilter { public static final String EXCLUSION_BLEND_FRAGMENT_SHADER = "varying highp vec2 textureCoordinate;\n" + diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageExposureFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageExposureFilter.java similarity index 81% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageExposureFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageExposureFilter.java index de5de414e..753e68649 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageExposureFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageExposureFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; import android.opengl.GLES20; @@ -35,8 +35,8 @@ public class GPUImageExposureFilter extends GPUImageFilter { " gl_FragColor = vec4(textureColor.rgb * pow(2.0, exposure), textureColor.w);\n" + " } "; - private int mExposureLocation; - private float mExposure; + private int exposureLocation; + private float exposure; public GPUImageExposureFilter() { this(1.0f); @@ -44,23 +44,23 @@ public GPUImageExposureFilter() { public GPUImageExposureFilter(final float exposure) { super(NO_FILTER_VERTEX_SHADER, EXPOSURE_FRAGMENT_SHADER); - mExposure = exposure; + this.exposure = exposure; } @Override public void onInit() { super.onInit(); - mExposureLocation = GLES20.glGetUniformLocation(getProgram(), "exposure"); + exposureLocation = GLES20.glGetUniformLocation(getProgram(), "exposure"); } @Override public void onInitialized() { super.onInitialized(); - setExposure(mExposure); + setExposure(exposure); } public void setExposure(final float exposure) { - mExposure = exposure; - setFloat(mExposureLocation, mExposure); + this.exposure = exposure; + setFloat(exposureLocation, this.exposure); } } diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageFalseColorFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageFalseColorFilter.java similarity index 75% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageFalseColorFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageFalseColorFilter.java index c815ad0fd..b19772dbd 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageFalseColorFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageFalseColorFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; import android.opengl.GLES20; @@ -39,10 +39,10 @@ public class GPUImageFalseColorFilter extends GPUImageFilter { "gl_FragColor = vec4( mix(firstColor.rgb, secondColor.rgb, luminance), textureColor.a);\n" + "}\n"; - private float[] mFirstColor; - private int mFirstColorLocation; - private float[] mSecondColor; - private int mSecondColorLocation; + private float[] firstColor; + private int firstColorLocation; + private float[] secondColor; + private int secondColorLocation; public GPUImageFalseColorFilter() { this(0f, 0f, 0.5f, 1f, 0f, 0f); @@ -54,31 +54,31 @@ public GPUImageFalseColorFilter(float firstRed, float firstGreen, float firstBlu public GPUImageFalseColorFilter(float[] firstColor, float[] secondColor) { super(NO_FILTER_VERTEX_SHADER, FALSECOLOR_FRAGMENT_SHADER); - mFirstColor = firstColor; - mSecondColor = secondColor; + this.firstColor = firstColor; + this.secondColor = secondColor; } @Override public void onInit() { super.onInit(); - mFirstColorLocation = GLES20.glGetUniformLocation(getProgram(), "firstColor"); - mSecondColorLocation = GLES20.glGetUniformLocation(getProgram(), "secondColor"); + firstColorLocation = GLES20.glGetUniformLocation(getProgram(), "firstColor"); + secondColorLocation = GLES20.glGetUniformLocation(getProgram(), "secondColor"); } @Override public void onInitialized() { super.onInitialized(); - setFirstColor(mFirstColor); - setSecondColor(mSecondColor); + setFirstColor(firstColor); + setSecondColor(secondColor); } public void setFirstColor(final float[] firstColor) { - mFirstColor = firstColor; - setFloatVec3(mFirstColorLocation, firstColor); + this.firstColor = firstColor; + setFloatVec3(firstColorLocation, firstColor); } public void setSecondColor(final float[] secondColor) { - mSecondColor = secondColor; - setFloatVec3(mSecondColorLocation, secondColor); + this.secondColor = secondColor; + setFloatVec3(secondColorLocation, secondColor); } } diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageFilter.java similarity index 71% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageFilter.java index 7a8641aaa..6139c4a11 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; import android.content.Context; import android.content.res.AssetManager; @@ -25,6 +25,8 @@ import java.nio.FloatBuffer; import java.util.LinkedList; +import jp.co.cyberagent.android.gpuimage.util.OpenGlUtils; + public class GPUImageFilter { public static final String NO_FILTER_VERTEX_SHADER = "" + "attribute vec4 position;\n" + @@ -47,48 +49,50 @@ public class GPUImageFilter { " gl_FragColor = texture2D(inputImageTexture, textureCoordinate);\n" + "}"; - private final LinkedList mRunOnDraw; - private final String mVertexShader; - private final String mFragmentShader; - protected int mGLProgId; - protected int mGLAttribPosition; - protected int mGLUniformTexture; - protected int mGLAttribTextureCoordinate; - protected int mOutputWidth; - protected int mOutputHeight; - private boolean mIsInitialized; + private final LinkedList runOnDraw; + private final String vertexShader; + private final String fragmentShader; + private int glProgId; + private int glAttribPosition; + private int glUniformTexture; + private int glAttribTextureCoordinate; + private int outputWidth; + private int outputHeight; + private boolean isInitialized; public GPUImageFilter() { this(NO_FILTER_VERTEX_SHADER, NO_FILTER_FRAGMENT_SHADER); } public GPUImageFilter(final String vertexShader, final String fragmentShader) { - mRunOnDraw = new LinkedList(); - mVertexShader = vertexShader; - mFragmentShader = fragmentShader; + runOnDraw = new LinkedList<>(); + this.vertexShader = vertexShader; + this.fragmentShader = fragmentShader; } - public final void init() { + private final void init() { onInit(); - mIsInitialized = true; onInitialized(); } public void onInit() { - mGLProgId = OpenGlUtils.loadProgram(mVertexShader, mFragmentShader); - mGLAttribPosition = GLES20.glGetAttribLocation(mGLProgId, "position"); - mGLUniformTexture = GLES20.glGetUniformLocation(mGLProgId, "inputImageTexture"); - mGLAttribTextureCoordinate = GLES20.glGetAttribLocation(mGLProgId, - "inputTextureCoordinate"); - mIsInitialized = true; + glProgId = OpenGlUtils.loadProgram(vertexShader, fragmentShader); + glAttribPosition = GLES20.glGetAttribLocation(glProgId, "position"); + glUniformTexture = GLES20.glGetUniformLocation(glProgId, "inputImageTexture"); + glAttribTextureCoordinate = GLES20.glGetAttribLocation(glProgId, "inputTextureCoordinate"); + isInitialized = true; } public void onInitialized() { } + public void ifNeedInit() { + if (!isInitialized) init(); + } + public final void destroy() { - mIsInitialized = false; - GLES20.glDeleteProgram(mGLProgId); + isInitialized = false; + GLES20.glDeleteProgram(glProgId); onDestroy(); } @@ -96,77 +100,81 @@ public void onDestroy() { } public void onOutputSizeChanged(final int width, final int height) { - mOutputWidth = width; - mOutputHeight = height; + outputWidth = width; + outputHeight = height; } public void onDraw(final int textureId, final FloatBuffer cubeBuffer, final FloatBuffer textureBuffer) { - GLES20.glUseProgram(mGLProgId); + GLES20.glUseProgram(glProgId); runPendingOnDrawTasks(); - if (!mIsInitialized) { + if (!isInitialized) { return; } cubeBuffer.position(0); - GLES20.glVertexAttribPointer(mGLAttribPosition, 2, GLES20.GL_FLOAT, false, 0, cubeBuffer); - GLES20.glEnableVertexAttribArray(mGLAttribPosition); + GLES20.glVertexAttribPointer(glAttribPosition, 2, GLES20.GL_FLOAT, false, 0, cubeBuffer); + GLES20.glEnableVertexAttribArray(glAttribPosition); textureBuffer.position(0); - GLES20.glVertexAttribPointer(mGLAttribTextureCoordinate, 2, GLES20.GL_FLOAT, false, 0, + GLES20.glVertexAttribPointer(glAttribTextureCoordinate, 2, GLES20.GL_FLOAT, false, 0, textureBuffer); - GLES20.glEnableVertexAttribArray(mGLAttribTextureCoordinate); + GLES20.glEnableVertexAttribArray(glAttribTextureCoordinate); if (textureId != OpenGlUtils.NO_TEXTURE) { GLES20.glActiveTexture(GLES20.GL_TEXTURE0); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId); - GLES20.glUniform1i(mGLUniformTexture, 0); + GLES20.glUniform1i(glUniformTexture, 0); } onDrawArraysPre(); GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); - GLES20.glDisableVertexAttribArray(mGLAttribPosition); - GLES20.glDisableVertexAttribArray(mGLAttribTextureCoordinate); + GLES20.glDisableVertexAttribArray(glAttribPosition); + GLES20.glDisableVertexAttribArray(glAttribTextureCoordinate); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0); } - protected void onDrawArraysPre() {} + protected void onDrawArraysPre() { + } protected void runPendingOnDrawTasks() { - while (!mRunOnDraw.isEmpty()) { - mRunOnDraw.removeFirst().run(); + synchronized (runOnDraw) { + while (!runOnDraw.isEmpty()) { + runOnDraw.removeFirst().run(); + } } } public boolean isInitialized() { - return mIsInitialized; + return isInitialized; } public int getOutputWidth() { - return mOutputWidth; + return outputWidth; } public int getOutputHeight() { - return mOutputHeight; + return outputHeight; } public int getProgram() { - return mGLProgId; + return glProgId; } public int getAttribPosition() { - return mGLAttribPosition; + return glAttribPosition; } public int getAttribTextureCoordinate() { - return mGLAttribTextureCoordinate; + return glAttribTextureCoordinate; } public int getUniformTexture() { - return mGLUniformTexture; + return glUniformTexture; } protected void setInteger(final int location, final int intValue) { runOnDraw(new Runnable() { @Override public void run() { + ifNeedInit(); GLES20.glUniform1i(location, intValue); } }); @@ -176,6 +184,7 @@ protected void setFloat(final int location, final float floatValue) { runOnDraw(new Runnable() { @Override public void run() { + ifNeedInit(); GLES20.glUniform1f(location, floatValue); } }); @@ -185,6 +194,7 @@ protected void setFloatVec2(final int location, final float[] arrayValue) { runOnDraw(new Runnable() { @Override public void run() { + ifNeedInit(); GLES20.glUniform2fv(location, 1, FloatBuffer.wrap(arrayValue)); } }); @@ -194,6 +204,7 @@ protected void setFloatVec3(final int location, final float[] arrayValue) { runOnDraw(new Runnable() { @Override public void run() { + ifNeedInit(); GLES20.glUniform3fv(location, 1, FloatBuffer.wrap(arrayValue)); } }); @@ -203,6 +214,7 @@ protected void setFloatVec4(final int location, final float[] arrayValue) { runOnDraw(new Runnable() { @Override public void run() { + ifNeedInit(); GLES20.glUniform4fv(location, 1, FloatBuffer.wrap(arrayValue)); } }); @@ -212,6 +224,7 @@ protected void setFloatArray(final int location, final float[] arrayValue) { runOnDraw(new Runnable() { @Override public void run() { + ifNeedInit(); GLES20.glUniform1fv(location, arrayValue.length, FloatBuffer.wrap(arrayValue)); } }); @@ -219,9 +232,9 @@ public void run() { protected void setPoint(final int location, final PointF point) { runOnDraw(new Runnable() { - @Override public void run() { + ifNeedInit(); float[] vec2 = new float[2]; vec2[0] = point.x; vec2[1] = point.y; @@ -235,6 +248,7 @@ protected void setUniformMatrix3f(final int location, final float[] matrix) { @Override public void run() { + ifNeedInit(); GLES20.glUniformMatrix3fv(location, 1, false, matrix, 0); } }); @@ -245,14 +259,15 @@ protected void setUniformMatrix4f(final int location, final float[] matrix) { @Override public void run() { + ifNeedInit(); GLES20.glUniformMatrix4fv(location, 1, false, matrix, 0); } }); } protected void runOnDraw(final Runnable runnable) { - synchronized (mRunOnDraw) { - mRunOnDraw.addLast(runnable); + synchronized (runOnDraw) { + runOnDraw.addLast(runnable); } } diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageFilterGroup.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageFilterGroup.java similarity index 62% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageFilterGroup.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageFilterGroup.java index 10ea41ca4..8735dbcdc 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageFilterGroup.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageFilterGroup.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,11 +14,10 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; import android.annotation.SuppressLint; import android.opengl.GLES20; -import jp.co.cyberagent.android.gpuimage.util.TextureRotationUtil; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -26,6 +25,9 @@ import java.util.ArrayList; import java.util.List; +import jp.co.cyberagent.android.gpuimage.util.Rotation; +import jp.co.cyberagent.android.gpuimage.util.TextureRotationUtil; + import static jp.co.cyberagent.android.gpuimage.GPUImageRenderer.CUBE; import static jp.co.cyberagent.android.gpuimage.util.TextureRotationUtil.TEXTURE_NO_ROTATION; @@ -35,14 +37,14 @@ */ public class GPUImageFilterGroup extends GPUImageFilter { - protected List mFilters; - protected List mMergedFilters; - private int[] mFrameBuffers; - private int[] mFrameBufferTextures; + private List filters; + private List mergedFilters; + private int[] frameBuffers; + private int[] frameBufferTextures; - private final FloatBuffer mGLCubeBuffer; - private final FloatBuffer mGLTextureBuffer; - private final FloatBuffer mGLTextureFlipBuffer; + private final FloatBuffer glCubeBuffer; + private final FloatBuffer glTextureBuffer; + private final FloatBuffer glTextureFlipBuffer; /** * Instantiates a new GPUImageFilterGroup with no filters. @@ -57,101 +59,101 @@ public GPUImageFilterGroup() { * @param filters the filters which represent this filter */ public GPUImageFilterGroup(List filters) { - mFilters = filters; - if (mFilters == null) { - mFilters = new ArrayList(); + this.filters = filters; + if (this.filters == null) { + this.filters = new ArrayList<>(); } else { updateMergedFilters(); } - mGLCubeBuffer = ByteBuffer.allocateDirect(CUBE.length * 4) + glCubeBuffer = ByteBuffer.allocateDirect(CUBE.length * 4) .order(ByteOrder.nativeOrder()) .asFloatBuffer(); - mGLCubeBuffer.put(CUBE).position(0); + glCubeBuffer.put(CUBE).position(0); - mGLTextureBuffer = ByteBuffer.allocateDirect(TEXTURE_NO_ROTATION.length * 4) + glTextureBuffer = ByteBuffer.allocateDirect(TEXTURE_NO_ROTATION.length * 4) .order(ByteOrder.nativeOrder()) .asFloatBuffer(); - mGLTextureBuffer.put(TEXTURE_NO_ROTATION).position(0); + glTextureBuffer.put(TEXTURE_NO_ROTATION).position(0); float[] flipTexture = TextureRotationUtil.getRotation(Rotation.NORMAL, false, true); - mGLTextureFlipBuffer = ByteBuffer.allocateDirect(flipTexture.length * 4) + glTextureFlipBuffer = ByteBuffer.allocateDirect(flipTexture.length * 4) .order(ByteOrder.nativeOrder()) .asFloatBuffer(); - mGLTextureFlipBuffer.put(flipTexture).position(0); + glTextureFlipBuffer.put(flipTexture).position(0); } public void addFilter(GPUImageFilter aFilter) { if (aFilter == null) { return; } - mFilters.add(aFilter); + filters.add(aFilter); updateMergedFilters(); } /* * (non-Javadoc) - * @see jp.co.cyberagent.android.gpuimage.GPUImageFilter#onInit() + * @see jp.co.cyberagent.android.gpuimage.filter.GPUImageFilter#onInit() */ @Override public void onInit() { super.onInit(); - for (GPUImageFilter filter : mFilters) { - filter.init(); + for (GPUImageFilter filter : filters) { + filter.ifNeedInit(); } } /* * (non-Javadoc) - * @see jp.co.cyberagent.android.gpuimage.GPUImageFilter#onDestroy() + * @see jp.co.cyberagent.android.gpuimage.filter.GPUImageFilter#onDestroy() */ @Override public void onDestroy() { destroyFramebuffers(); - for (GPUImageFilter filter : mFilters) { + for (GPUImageFilter filter : filters) { filter.destroy(); } super.onDestroy(); } private void destroyFramebuffers() { - if (mFrameBufferTextures != null) { - GLES20.glDeleteTextures(mFrameBufferTextures.length, mFrameBufferTextures, 0); - mFrameBufferTextures = null; + if (frameBufferTextures != null) { + GLES20.glDeleteTextures(frameBufferTextures.length, frameBufferTextures, 0); + frameBufferTextures = null; } - if (mFrameBuffers != null) { - GLES20.glDeleteFramebuffers(mFrameBuffers.length, mFrameBuffers, 0); - mFrameBuffers = null; + if (frameBuffers != null) { + GLES20.glDeleteFramebuffers(frameBuffers.length, frameBuffers, 0); + frameBuffers = null; } } /* * (non-Javadoc) * @see - * jp.co.cyberagent.android.gpuimage.GPUImageFilter#onOutputSizeChanged(int, + * jp.co.cyberagent.android.gpuimage.filter.GPUImageFilter#onOutputSizeChanged(int, * int) */ @Override public void onOutputSizeChanged(final int width, final int height) { super.onOutputSizeChanged(width, height); - if (mFrameBuffers != null) { + if (frameBuffers != null) { destroyFramebuffers(); } - int size = mFilters.size(); + int size = filters.size(); for (int i = 0; i < size; i++) { - mFilters.get(i).onOutputSizeChanged(width, height); + filters.get(i).onOutputSizeChanged(width, height); } - if (mMergedFilters != null && mMergedFilters.size() > 0) { - size = mMergedFilters.size(); - mFrameBuffers = new int[size - 1]; - mFrameBufferTextures = new int[size - 1]; + if (mergedFilters != null && mergedFilters.size() > 0) { + size = mergedFilters.size(); + frameBuffers = new int[size - 1]; + frameBufferTextures = new int[size - 1]; for (int i = 0; i < size - 1; i++) { - GLES20.glGenFramebuffers(1, mFrameBuffers, i); - GLES20.glGenTextures(1, mFrameBufferTextures, i); - GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mFrameBufferTextures[i]); + GLES20.glGenFramebuffers(1, frameBuffers, i); + GLES20.glGenTextures(1, frameBufferTextures, i); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, frameBufferTextures[i]); GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null); GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, @@ -163,9 +165,9 @@ public void onOutputSizeChanged(final int width, final int height) { GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); - GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFrameBuffers[i]); + GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frameBuffers[i]); GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, - GLES20.GL_TEXTURE_2D, mFrameBufferTextures[i], 0); + GLES20.GL_TEXTURE_2D, frameBufferTextures[i], 0); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0); GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); @@ -175,43 +177,43 @@ public void onOutputSizeChanged(final int width, final int height) { /* * (non-Javadoc) - * @see jp.co.cyberagent.android.gpuimage.GPUImageFilter#onDraw(int, + * @see jp.co.cyberagent.android.gpuimage.filter.GPUImageFilter#onDraw(int, * java.nio.FloatBuffer, java.nio.FloatBuffer) */ - @SuppressLint("WrongCall") + @SuppressLint("WrongCall") @Override public void onDraw(final int textureId, final FloatBuffer cubeBuffer, final FloatBuffer textureBuffer) { runPendingOnDrawTasks(); - if (!isInitialized() || mFrameBuffers == null || mFrameBufferTextures == null) { + if (!isInitialized() || frameBuffers == null || frameBufferTextures == null) { return; } - if (mMergedFilters != null) { - int size = mMergedFilters.size(); + if (mergedFilters != null) { + int size = mergedFilters.size(); int previousTexture = textureId; for (int i = 0; i < size; i++) { - GPUImageFilter filter = mMergedFilters.get(i); + GPUImageFilter filter = mergedFilters.get(i); boolean isNotLast = i < size - 1; if (isNotLast) { - GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFrameBuffers[i]); + GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frameBuffers[i]); GLES20.glClearColor(0, 0, 0, 0); } if (i == 0) { filter.onDraw(previousTexture, cubeBuffer, textureBuffer); } else if (i == size - 1) { - filter.onDraw(previousTexture, mGLCubeBuffer, (size % 2 == 0) ? mGLTextureFlipBuffer : mGLTextureBuffer); + filter.onDraw(previousTexture, glCubeBuffer, (size % 2 == 0) ? glTextureFlipBuffer : glTextureBuffer); } else { - filter.onDraw(previousTexture, mGLCubeBuffer, mGLTextureBuffer); + filter.onDraw(previousTexture, glCubeBuffer, glTextureBuffer); } if (isNotLast) { GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); - previousTexture = mFrameBufferTextures[i]; + previousTexture = frameBufferTextures[i]; } } } - } + } /** * Gets the filters. @@ -219,35 +221,35 @@ public void onDraw(final int textureId, final FloatBuffer cubeBuffer, * @return the filters */ public List getFilters() { - return mFilters; + return filters; } public List getMergedFilters() { - return mMergedFilters; + return mergedFilters; } public void updateMergedFilters() { - if (mFilters == null) { + if (filters == null) { return; } - if (mMergedFilters == null) { - mMergedFilters = new ArrayList(); + if (mergedFilters == null) { + mergedFilters = new ArrayList<>(); } else { - mMergedFilters.clear(); + mergedFilters.clear(); } List filters; - for (GPUImageFilter filter : mFilters) { + for (GPUImageFilter filter : this.filters) { if (filter instanceof GPUImageFilterGroup) { ((GPUImageFilterGroup) filter).updateMergedFilters(); filters = ((GPUImageFilterGroup) filter).getMergedFilters(); if (filters == null || filters.isEmpty()) continue; - mMergedFilters.addAll(filters); + mergedFilters.addAll(filters); continue; } - mMergedFilters.add(filter); + mergedFilters.add(filter); } } } diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageGammaFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageGammaFilter.java similarity index 82% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageGammaFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageGammaFilter.java index 1f902d0f6..94e5296a7 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageGammaFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageGammaFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; import android.opengl.GLES20; @@ -35,8 +35,8 @@ public class GPUImageGammaFilter extends GPUImageFilter { " gl_FragColor = vec4(pow(textureColor.rgb, vec3(gamma)), textureColor.w);\n" + " }"; - private int mGammaLocation; - private float mGamma; + private int gammaLocation; + private float gamma; public GPUImageGammaFilter() { this(1.2f); @@ -44,23 +44,23 @@ public GPUImageGammaFilter() { public GPUImageGammaFilter(final float gamma) { super(NO_FILTER_VERTEX_SHADER, GAMMA_FRAGMENT_SHADER); - mGamma = gamma; + this.gamma = gamma; } @Override public void onInit() { super.onInit(); - mGammaLocation = GLES20.glGetUniformLocation(getProgram(), "gamma"); + gammaLocation = GLES20.glGetUniformLocation(getProgram(), "gamma"); } @Override public void onInitialized() { super.onInitialized(); - setGamma(mGamma); + setGamma(gamma); } public void setGamma(final float gamma) { - mGamma = gamma; - setFloat(mGammaLocation, mGamma); + this.gamma = gamma; + setFloat(gammaLocation, this.gamma); } } diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageGaussianBlurFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageGaussianBlurFilter.java similarity index 92% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageGaussianBlurFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageGaussianBlurFilter.java index c912f73ef..c945a07ea 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageGaussianBlurFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageGaussianBlurFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; /** * A more generalized 9x9 Gaussian blur filter @@ -78,7 +78,7 @@ public class GPUImageGaussianBlurFilter extends GPUImageTwoPassTextureSamplingFi " gl_FragColor = vec4(sum,fragColor.a);\n" + "}"; - protected float mBlurSize = 1f; + protected float blurSize; public GPUImageGaussianBlurFilter() { this(1f); @@ -86,17 +86,23 @@ public GPUImageGaussianBlurFilter() { public GPUImageGaussianBlurFilter(float blurSize) { super(VERTEX_SHADER, FRAGMENT_SHADER, VERTEX_SHADER, FRAGMENT_SHADER); - mBlurSize = blurSize; + this.blurSize = blurSize; + } + + @Override + public void onInitialized() { + super.onInitialized(); + setBlurSize(blurSize); } @Override public float getVerticalTexelOffsetRatio() { - return mBlurSize; + return blurSize; } @Override public float getHorizontalTexelOffsetRatio() { - return mBlurSize; + return blurSize; } /** @@ -105,7 +111,7 @@ public float getHorizontalTexelOffsetRatio() { * @param blurSize from 0.0 on up, default 1.0 */ public void setBlurSize(float blurSize) { - mBlurSize = blurSize; + this.blurSize = blurSize; runOnDraw(new Runnable() { @Override public void run() { diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageGlassSphereFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageGlassSphereFilter.java similarity index 73% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageGlassSphereFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageGlassSphereFilter.java index 460019cc0..e43b348a7 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageGlassSphereFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageGlassSphereFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; import android.graphics.PointF; import android.opengl.GLES20; @@ -61,14 +61,14 @@ public class GPUImageGlassSphereFilter extends GPUImageFilter { "gl_FragColor = vec4(finalSphereColor, 1.0) * checkForPresenceWithinSphere;\n" + "}\n"; - private PointF mCenter; - private int mCenterLocation; - private float mRadius; - private int mRadiusLocation; - private float mAspectRatio; - private int mAspectRatioLocation; - private float mRefractiveIndex; - private int mRefractiveIndexLocation; + private PointF center; + private int centerLocation; + private float radius; + private int radiusLocation; + private float aspectRatio; + private int aspectRatioLocation; + private float refractiveIndex; + private int refractiveIndexLocation; public GPUImageGlassSphereFilter() { this(new PointF(0.5f, 0.5f), 0.25f, 0.71f); @@ -76,52 +76,53 @@ public GPUImageGlassSphereFilter() { public GPUImageGlassSphereFilter(PointF center, float radius, float refractiveIndex) { super(NO_FILTER_VERTEX_SHADER, SPHERE_FRAGMENT_SHADER); - mCenter = center; - mRadius = radius; - mRefractiveIndex = refractiveIndex; + this.center = center; + this.radius = radius; + this.refractiveIndex = refractiveIndex; } @Override public void onInit() { super.onInit(); - mCenterLocation = GLES20.glGetUniformLocation(getProgram(), "center"); - mRadiusLocation = GLES20.glGetUniformLocation(getProgram(), "radius"); - mAspectRatioLocation = GLES20.glGetUniformLocation(getProgram(), "aspectRatio"); - mRefractiveIndexLocation = GLES20.glGetUniformLocation(getProgram(), "refractiveIndex"); + centerLocation = GLES20.glGetUniformLocation(getProgram(), "center"); + radiusLocation = GLES20.glGetUniformLocation(getProgram(), "radius"); + aspectRatioLocation = GLES20.glGetUniformLocation(getProgram(), "aspectRatio"); + refractiveIndexLocation = GLES20.glGetUniformLocation(getProgram(), "refractiveIndex"); } @Override public void onInitialized() { super.onInitialized(); - setRadius(mRadius); - setCenter(mCenter); - setRefractiveIndex(mRefractiveIndex); + setAspectRatio(aspectRatio); + setRadius(radius); + setCenter(center); + setRefractiveIndex(refractiveIndex); } @Override public void onOutputSizeChanged(int width, int height) { - mAspectRatio = (float) height / width; - setAspectRatio(mAspectRatio); + aspectRatio = (float) height / width; + setAspectRatio(aspectRatio); super.onOutputSizeChanged(width, height); } private void setAspectRatio(float aspectRatio) { - mAspectRatio = aspectRatio; - setFloat(mAspectRatioLocation, aspectRatio); + this.aspectRatio = aspectRatio; + setFloat(aspectRatioLocation, aspectRatio); } public void setRefractiveIndex(float refractiveIndex) { - mRefractiveIndex = refractiveIndex; - setFloat(mRefractiveIndexLocation, refractiveIndex); + this.refractiveIndex = refractiveIndex; + setFloat(refractiveIndexLocation, refractiveIndex); } public void setCenter(PointF center) { - mCenter = center; - setPoint(mCenterLocation, center); + this.center = center; + setPoint(centerLocation, center); } public void setRadius(float radius) { - mRadius = radius; - setFloat(mRadiusLocation, radius); + this.radius = radius; + setFloat(radiusLocation, radius); } } diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageGrayscaleFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageGrayscaleFilter.java similarity index 94% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageGrayscaleFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageGrayscaleFilter.java index b0a67f9ef..3f658646a 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageGrayscaleFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageGrayscaleFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; /** * Applies a grayscale effect to the image. diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageHalftoneFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageHalftoneFilter.java similarity index 68% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageHalftoneFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageHalftoneFilter.java index 52e27d046..1bde2b9a5 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageHalftoneFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageHalftoneFilter.java @@ -1,4 +1,4 @@ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; import android.opengl.GLES20; @@ -26,11 +26,11 @@ public class GPUImageHalftoneFilter extends GPUImageFilter { " gl_FragColor = vec4(vec3(checkForPresenceWithinDot), 1.0);\n" + "}"; - private int mFractionalWidthOfPixelLocation; - private int mAspectRatioLocation; + private int fractionalWidthOfPixelLocation; + private int aspectRatioLocation; - private float mFractionalWidthOfAPixel; - private float mAspectRatio; + private float fractionalWidthOfAPixel; + private float aspectRatio; public GPUImageHalftoneFilter() { this(0.01f); @@ -38,30 +38,36 @@ public GPUImageHalftoneFilter() { public GPUImageHalftoneFilter(float fractionalWidthOfAPixel) { super(NO_FILTER_VERTEX_SHADER, HALFTONE_FRAGMENT_SHADER); - mFractionalWidthOfAPixel = fractionalWidthOfAPixel; + this.fractionalWidthOfAPixel = fractionalWidthOfAPixel; } @Override public void onInit() { super.onInit(); - mFractionalWidthOfPixelLocation = GLES20.glGetUniformLocation(getProgram(), "fractionalWidthOfPixel"); - mAspectRatioLocation = GLES20.glGetUniformLocation(getProgram(), "aspectRatio"); - setFractionalWidthOfAPixel(mFractionalWidthOfAPixel); + fractionalWidthOfPixelLocation = GLES20.glGetUniformLocation(getProgram(), "fractionalWidthOfPixel"); + aspectRatioLocation = GLES20.glGetUniformLocation(getProgram(), "aspectRatio"); + } + + @Override + public void onInitialized() { + super.onInitialized(); + setFractionalWidthOfAPixel(fractionalWidthOfAPixel); + setAspectRatio(aspectRatio); } @Override public void onOutputSizeChanged(final int width, final int height) { super.onOutputSizeChanged(width, height); - setAspectRatio((float)height / (float) width); + setAspectRatio((float) height / (float) width); } public void setFractionalWidthOfAPixel(final float fractionalWidthOfAPixel) { - mFractionalWidthOfAPixel = fractionalWidthOfAPixel; - setFloat(mFractionalWidthOfPixelLocation, mFractionalWidthOfAPixel); + this.fractionalWidthOfAPixel = fractionalWidthOfAPixel; + setFloat(fractionalWidthOfPixelLocation, this.fractionalWidthOfAPixel); } public void setAspectRatio(final float aspectRatio) { - mAspectRatio = aspectRatio; - setFloat(mAspectRatioLocation, mAspectRatio); + this.aspectRatio = aspectRatio; + setFloat(aspectRatioLocation, this.aspectRatio); } } diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageHardLightBlendFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageHardLightBlendFilter.java similarity index 96% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageHardLightBlendFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageHardLightBlendFilter.java index 5bcb9c90b..57cc142b7 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageHardLightBlendFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageHardLightBlendFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; public class GPUImageHardLightBlendFilter extends GPUImageTwoInputFilter { public static final String HARD_LIGHT_BLEND_FRAGMENT_SHADER = "varying highp vec2 textureCoordinate;\n" + diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageHazeFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageHazeFilter.java similarity index 79% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageHazeFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageHazeFilter.java index bb230abc9..11da6f3d0 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageHazeFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageHazeFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,13 +14,13 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; import android.opengl.GLES20; /** * The haze filter can be used to add or remove haze. - * + *

* This is similar to a UV filter. */ public class GPUImageHazeFilter extends GPUImageFilter { @@ -46,10 +46,10 @@ public class GPUImageHazeFilter extends GPUImageFilter { " gl_FragColor = c; //consider using premultiply(c);\n" + "}\n"; - private float mDistance; - private int mDistanceLocation; - private float mSlope; - private int mSlopeLocation; + private float distance; + private int distanceLocation; + private float slope; + private int slopeLocation; public GPUImageHazeFilter() { this(0.2f, 0.0f); @@ -57,22 +57,22 @@ public GPUImageHazeFilter() { public GPUImageHazeFilter(float distance, float slope) { super(NO_FILTER_VERTEX_SHADER, HAZE_FRAGMENT_SHADER); - mDistance = distance; - mSlope = slope; + this.distance = distance; + this.slope = slope; } @Override public void onInit() { super.onInit(); - mDistanceLocation = GLES20.glGetUniformLocation(getProgram(), "distance"); - mSlopeLocation = GLES20.glGetUniformLocation(getProgram(), "slope"); + distanceLocation = GLES20.glGetUniformLocation(getProgram(), "distance"); + slopeLocation = GLES20.glGetUniformLocation(getProgram(), "slope"); } @Override public void onInitialized() { super.onInitialized(); - setDistance(mDistance); - setSlope(mSlope); + setDistance(distance); + setSlope(slope); } /** @@ -81,8 +81,8 @@ public void onInitialized() { * @param distance -0.3 to 0.3 are best, default 0 */ public void setDistance(float distance) { - mDistance = distance; - setFloat(mDistanceLocation, distance); + this.distance = distance; + setFloat(distanceLocation, distance); } /** @@ -91,7 +91,7 @@ public void setDistance(float distance) { * @param slope -0.3 to 0.3 are best, default 0 */ public void setSlope(float slope) { - mSlope = slope; - setFloat(mSlopeLocation, slope); + this.slope = slope; + setFloat(slopeLocation, slope); } } diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageHighlightShadowFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageHighlightShadowFilter.java similarity index 79% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageHighlightShadowFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageHighlightShadowFilter.java index 878c508a9..37eabb96a 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageHighlightShadowFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageHighlightShadowFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; import android.opengl.GLES20; @@ -45,10 +45,10 @@ public class GPUImageHighlightShadowFilter extends GPUImageFilter { " gl_FragColor = vec4(result.rgb, source.a);\n" + " }"; - private int mShadowsLocation; - private float mShadows; - private int mHighlightsLocation; - private float mHighlights; + private int shadowsLocation; + private float shadows; + private int highlightsLocation; + private float highlights; public GPUImageHighlightShadowFilter() { this(0.0f, 1.0f); @@ -56,31 +56,31 @@ public GPUImageHighlightShadowFilter() { public GPUImageHighlightShadowFilter(final float shadows, final float highlights) { super(NO_FILTER_VERTEX_SHADER, HIGHLIGHT_SHADOW_FRAGMENT_SHADER); - mHighlights = highlights; - mShadows = shadows; + this.highlights = highlights; + this.shadows = shadows; } @Override public void onInit() { super.onInit(); - mHighlightsLocation = GLES20.glGetUniformLocation(getProgram(), "highlights"); - mShadowsLocation = GLES20.glGetUniformLocation(getProgram(), "shadows"); + highlightsLocation = GLES20.glGetUniformLocation(getProgram(), "highlights"); + shadowsLocation = GLES20.glGetUniformLocation(getProgram(), "shadows"); } @Override public void onInitialized() { super.onInitialized(); - setHighlights(mHighlights); - setShadows(mShadows); + setHighlights(highlights); + setShadows(shadows); } public void setHighlights(final float highlights) { - mHighlights = highlights; - setFloat(mHighlightsLocation, mHighlights); + this.highlights = highlights; + setFloat(highlightsLocation, this.highlights); } - + public void setShadows(final float shadows) { - mShadows = shadows; - setFloat(mShadowsLocation, mShadows); + this.shadows = shadows; + setFloat(shadowsLocation, this.shadows); } } diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageHueBlendFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageHueBlendFilter.java similarity index 98% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageHueBlendFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageHueBlendFilter.java index 3950901c7..143e3fc71 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageHueBlendFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageHueBlendFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; public class GPUImageHueBlendFilter extends GPUImageTwoInputFilter { public static final String HUE_BLEND_FRAGMENT_SHADER = "varying highp vec2 textureCoordinate;\n" + diff --git a/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageHueFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageHueFilter.java new file mode 100644 index 000000000..ce9303051 --- /dev/null +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageHueFilter.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2018 CyberAgent, Inc. + * + * 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 jp.co.cyberagent.android.gpuimage.filter; + +import android.opengl.GLES20; + +public class GPUImageHueFilter extends GPUImageFilter { + public static final String HUE_FRAGMENT_SHADER = "" + + "precision highp float;\n" + + "varying highp vec2 textureCoordinate;\n" + + "\n" + + "uniform sampler2D inputImageTexture;\n" + + "uniform mediump float hueAdjust;\n" + + "const highp vec4 kRGBToYPrime = vec4 (0.299, 0.587, 0.114, 0.0);\n" + + "const highp vec4 kRGBToI = vec4 (0.595716, -0.274453, -0.321263, 0.0);\n" + + "const highp vec4 kRGBToQ = vec4 (0.211456, -0.522591, 0.31135, 0.0);\n" + + "\n" + + "const highp vec4 kYIQToR = vec4 (1.0, 0.9563, 0.6210, 0.0);\n" + + "const highp vec4 kYIQToG = vec4 (1.0, -0.2721, -0.6474, 0.0);\n" + + "const highp vec4 kYIQToB = vec4 (1.0, -1.1070, 1.7046, 0.0);\n" + + "\n" + + "void main ()\n" + + "{\n" + + " // Sample the input pixel\n" + + " highp vec4 color = texture2D(inputImageTexture, textureCoordinate);\n" + + "\n" + + " // Convert to YIQ\n" + + " highp float YPrime = dot (color, kRGBToYPrime);\n" + + " highp float I = dot (color, kRGBToI);\n" + + " highp float Q = dot (color, kRGBToQ);\n" + + "\n" + + " // Calculate the hue and chroma\n" + + " highp float hue = atan (Q, I);\n" + + " highp float chroma = sqrt (I * I + Q * Q);\n" + + "\n" + + " // Make the user's adjustments\n" + + " hue += (-hueAdjust); //why negative rotation?\n" + + "\n" + + " // Convert back to YIQ\n" + + " Q = chroma * sin (hue);\n" + + " I = chroma * cos (hue);\n" + + "\n" + + " // Convert back to RGB\n" + + " highp vec4 yIQ = vec4 (YPrime, I, Q, 0.0);\n" + + " color.r = dot (yIQ, kYIQToR);\n" + + " color.g = dot (yIQ, kYIQToG);\n" + + " color.b = dot (yIQ, kYIQToB);\n" + + "\n" + + " // Save the result\n" + + " gl_FragColor = color;\n" + + "}\n"; + + private float hue; + private int hueLocation; + + public GPUImageHueFilter() { + this(90.0f); + } + + public GPUImageHueFilter(final float hue) { + super(NO_FILTER_VERTEX_SHADER, HUE_FRAGMENT_SHADER); + this.hue = hue; + } + + @Override + public void onInit() { + super.onInit(); + hueLocation = GLES20.glGetUniformLocation(getProgram(), "hueAdjust"); + } + + @Override + public void onInitialized() { + super.onInitialized(); + setHue(hue); + } + + public void setHue(final float hue) { + this.hue = hue; + float hueAdjust = (this.hue % 360.0f) * (float) Math.PI / 180.0f; + setFloat(hueLocation, hueAdjust); + } +} diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageKuwaharaFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageKuwaharaFilter.java similarity index 93% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageKuwaharaFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageKuwaharaFilter.java index 6fc7f32bc..f047e61ab 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageKuwaharaFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageKuwaharaFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; import android.opengl.GLES20; @@ -114,8 +114,8 @@ public class GPUImageKuwaharaFilter extends GPUImageFilter { "}\n" + "}\n"; - private int mRadius; - private int mRadiusLocation; + private int radius; + private int radiusLocation; public GPUImageKuwaharaFilter() { this(3); @@ -123,19 +123,19 @@ public GPUImageKuwaharaFilter() { public GPUImageKuwaharaFilter(int radius) { super(NO_FILTER_VERTEX_SHADER, KUWAHARA_FRAGMENT_SHADER); - mRadius = radius; + this.radius = radius; } @Override public void onInit() { super.onInit(); - mRadiusLocation = GLES20.glGetUniformLocation(getProgram(), "radius"); + radiusLocation = GLES20.glGetUniformLocation(getProgram(), "radius"); } @Override public void onInitialized() { super.onInitialized(); - setRadius(mRadius); + setRadius(radius); } /** @@ -145,7 +145,7 @@ public void onInitialized() { * @param radius default 3 */ public void setRadius(final int radius) { - mRadius = radius; - setInteger(mRadiusLocation, radius); + this.radius = radius; + setInteger(radiusLocation, radius); } } diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageLaplacianFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageLaplacianFilter.java similarity index 86% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageLaplacianFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageLaplacianFilter.java index d320f64d8..566927a43 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageLaplacianFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageLaplacianFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; import android.opengl.GLES20; @@ -60,8 +60,8 @@ public class GPUImageLaplacianFilter extends GPUImage3x3TextureSamplingFilter { "gl_FragColor = vec4(resultColor, centerColor.a);\n" + "}\n"; - private float[] mConvolutionKernel; - private int mUniformConvolutionMatrix; + private float[] convolutionKernel; + private int uniformConvolutionMatrix; public GPUImageLaplacianFilter() { this(new float[]{ @@ -73,18 +73,23 @@ public GPUImageLaplacianFilter() { private GPUImageLaplacianFilter(final float[] convolutionKernel) { super(LAPLACIAN_FRAGMENT_SHADER); - mConvolutionKernel = convolutionKernel; + this.convolutionKernel = convolutionKernel; } @Override public void onInit() { super.onInit(); - mUniformConvolutionMatrix = GLES20.glGetUniformLocation(getProgram(), "convolutionMatrix"); - setConvolutionKernel(mConvolutionKernel); + uniformConvolutionMatrix = GLES20.glGetUniformLocation(getProgram(), "convolutionMatrix"); + } + + @Override + public void onInitialized() { + super.onInitialized(); + setConvolutionKernel(convolutionKernel); } private void setConvolutionKernel(final float[] convolutionKernel) { - mConvolutionKernel = convolutionKernel; - setUniformMatrix3f(mUniformConvolutionMatrix, mConvolutionKernel); + this.convolutionKernel = convolutionKernel; + setUniformMatrix3f(uniformConvolutionMatrix, this.convolutionKernel); } } diff --git a/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageLevelsFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageLevelsFilter.java new file mode 100644 index 000000000..3ceaca5b3 --- /dev/null +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageLevelsFilter.java @@ -0,0 +1,129 @@ +package jp.co.cyberagent.android.gpuimage.filter; + +import android.opengl.GLES20; + +/** + * Created by vashisthg 30/05/14. + */ +public class GPUImageLevelsFilter extends GPUImageFilter { + + private static final String LOGTAG = GPUImageLevelsFilter.class.getSimpleName(); + + public static final String LEVELS_FRAGMET_SHADER = + + " varying highp vec2 textureCoordinate;\n" + + " \n" + + " uniform sampler2D inputImageTexture;\n" + + " uniform mediump vec3 levelMinimum;\n" + + " uniform mediump vec3 levelMiddle;\n" + + " uniform mediump vec3 levelMaximum;\n" + + " uniform mediump vec3 minOutput;\n" + + " uniform mediump vec3 maxOutput;\n" + + " \n" + + " void main()\n" + + " {\n" + + " mediump vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);\n" + + " \n" + + " gl_FragColor = vec4( mix(minOutput, maxOutput, pow(min(max(textureColor.rgb -levelMinimum, vec3(0.0)) / (levelMaximum - levelMinimum ), vec3(1.0)), 1.0 /levelMiddle)) , textureColor.a);\n" + + " }\n"; + + private int minLocation; + private float[] min; + private int midLocation; + private float[] mid; + private int maxLocation; + private float[] max; + private int minOutputLocation; + private float[] minOutput; + private int maxOutputLocation; + private float[] maxOutput; + + public GPUImageLevelsFilter() { + this(new float[]{0.0f, 0.0f, 0.0f}, new float[]{1.0f, 1.0f, 1.0f}, new float[]{1.0f, 1.0f, 1.0f}, new float[]{0.0f, 0.0f, 0.0f}, new float[]{1.0f, 1.0f, 1.0f}); + } + + private GPUImageLevelsFilter(final float[] min, final float[] mid, final float[] max, final float[] minOUt, final float[] maxOut) { + super(NO_FILTER_VERTEX_SHADER, LEVELS_FRAGMET_SHADER); + + this.min = min; + this.mid = mid; + this.max = max; + minOutput = minOUt; + maxOutput = maxOut; + } + + @Override + public void onInit() { + super.onInit(); + minLocation = GLES20.glGetUniformLocation(getProgram(), "levelMinimum"); + midLocation = GLES20.glGetUniformLocation(getProgram(), "levelMiddle"); + maxLocation = GLES20.glGetUniformLocation(getProgram(), "levelMaximum"); + minOutputLocation = GLES20.glGetUniformLocation(getProgram(), "minOutput"); + maxOutputLocation = GLES20.glGetUniformLocation(getProgram(), "maxOutput"); + } + + @Override + public void onInitialized() { + super.onInitialized(); + setMin(0.0f, 1.0f, 1.0f, 0.0f, 1.0f); + updateUniforms(); + } + + + public void updateUniforms() { + setFloatVec3(minLocation, min); + setFloatVec3(midLocation, mid); + setFloatVec3(maxLocation, max); + setFloatVec3(minOutputLocation, minOutput); + setFloatVec3(maxOutputLocation, maxOutput); + } + + public void setMin(float min, float mid, float max, float minOut, float maxOut) { + setRedMin(min, mid, max, minOut, maxOut); + setGreenMin(min, mid, max, minOut, maxOut); + setBlueMin(min, mid, max, minOut, maxOut); + } + + public void setMin(float min, float mid, float max) { + setMin(min, mid, max, 0.0f, 1.0f); + } + + public void setRedMin(float min, float mid, float max, float minOut, float maxOut) { + this.min[0] = min; + this.mid[0] = mid; + this.max[0] = max; + minOutput[0] = minOut; + maxOutput[0] = maxOut; + updateUniforms(); + } + + public void setRedMin(float min, float mid, float max) { + setRedMin(min, mid, max, 0, 1); + } + + public void setGreenMin(float min, float mid, float max, float minOut, float maxOut) { + this.min[1] = min; + this.mid[1] = mid; + this.max[1] = max; + minOutput[1] = minOut; + maxOutput[1] = maxOut; + updateUniforms(); + } + + public void setGreenMin(float min, float mid, float max) { + setGreenMin(min, mid, max, 0, 1); + } + + public void setBlueMin(float min, float mid, float max, float minOut, float maxOut) { + this.min[2] = min; + this.mid[2] = mid; + this.max[2] = max; + minOutput[2] = minOut; + maxOutput[2] = maxOut; + updateUniforms(); + } + + public void setBlueMin(float min, float mid, float max) { + setBlueMin(min, mid, max, 0, 1); + } +} diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageLightenBlendFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageLightenBlendFilter.java similarity index 94% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageLightenBlendFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageLightenBlendFilter.java index 77399cb18..6a6e07235 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageLightenBlendFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageLightenBlendFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; public class GPUImageLightenBlendFilter extends GPUImageTwoInputFilter { public static final String LIGHTEN_BLEND_FRAGMENT_SHADER = "varying highp vec2 textureCoordinate;\n" + diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageLinearBurnBlendFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageLinearBurnBlendFilter.java similarity index 94% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageLinearBurnBlendFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageLinearBurnBlendFilter.java index 2623b528e..dba215526 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageLinearBurnBlendFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageLinearBurnBlendFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; public class GPUImageLinearBurnBlendFilter extends GPUImageTwoInputFilter { public static final String LINEAR_BURN_BLEND_FRAGMENT_SHADER = "varying highp vec2 textureCoordinate;\n" + diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageLookupFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageLookupFilter.java similarity index 88% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageLookupFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageLookupFilter.java index 42c9ebdcb..df56675d2 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageLookupFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageLookupFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; import android.opengl.GLES20; @@ -57,8 +57,8 @@ public class GPUImageLookupFilter extends GPUImageTwoInputFilter { " gl_FragColor = mix(textureColor, vec4(newColor.rgb, textureColor.w), intensity);\n" + " }"; - private int mIntensityLocation; - private float mIntensity; + private int intensityLocation; + private float intensity; public GPUImageLookupFilter() { this(1.0f); @@ -66,23 +66,23 @@ public GPUImageLookupFilter() { public GPUImageLookupFilter(final float intensity) { super(LOOKUP_FRAGMENT_SHADER); - mIntensity = intensity; + this.intensity = intensity; } @Override public void onInit() { super.onInit(); - mIntensityLocation = GLES20.glGetUniformLocation(getProgram(), "intensity"); + intensityLocation = GLES20.glGetUniformLocation(getProgram(), "intensity"); } @Override public void onInitialized() { super.onInitialized(); - setIntensity(mIntensity); + setIntensity(intensity); } public void setIntensity(final float intensity) { - mIntensity = intensity; - setFloat(mIntensityLocation, mIntensity); + this.intensity = intensity; + setFloat(intensityLocation, this.intensity); } } diff --git a/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageLuminanceFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageLuminanceFilter.java new file mode 100644 index 000000000..4a4e77073 --- /dev/null +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageLuminanceFilter.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2018 CyberAgent, Inc. + * + * 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 jp.co.cyberagent.android.gpuimage.filter; + +public class GPUImageLuminanceFilter extends GPUImageFilter { + + public static final String LUMINANCE_FRAGMENT_SHADER = "" + + "precision highp float;\n" + + "\n" + + "varying vec2 textureCoordinate;\n" + + "\n" + + "uniform sampler2D inputImageTexture;\n" + + "\n" + + "// Values from \"Graphics Shaders: Theory and Practice\" by Bailey and Cunningham\n" + + "const highp vec3 W = vec3(0.2125, 0.7154, 0.0721);\n" + + "\n" + + "void main()\n" + + "{\n" + + " lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);\n" + + " float luminance = dot(textureColor.rgb, W);\n" + + " \n" + + " gl_FragColor = vec4(vec3(luminance), textureColor.a);\n" + + "}"; + + public GPUImageLuminanceFilter() { + super(NO_FILTER_VERTEX_SHADER, LUMINANCE_FRAGMENT_SHADER); + } +} diff --git a/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageLuminanceThresholdFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageLuminanceThresholdFilter.java new file mode 100644 index 000000000..415ef5a11 --- /dev/null +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageLuminanceThresholdFilter.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2018 CyberAgent, Inc. + * + * 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 jp.co.cyberagent.android.gpuimage.filter; + +import android.opengl.GLES20; + +public class GPUImageLuminanceThresholdFilter extends GPUImageFilter { + + public static final String LUMINANCE_THRESHOLD_FRAGMENT_SHADER = "" + + "varying highp vec2 textureCoordinate;\n" + + "\n" + + "uniform sampler2D inputImageTexture;\n" + + "uniform highp float threshold;\n" + + "\n" + + "const highp vec3 W = vec3(0.2125, 0.7154, 0.0721);\n" + + "\n" + + "void main()\n" + + "{\n" + + " highp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);\n" + + " highp float luminance = dot(textureColor.rgb, W);\n" + + " highp float thresholdResult = step(threshold, luminance);\n" + + " \n" + + " gl_FragColor = vec4(vec3(thresholdResult), textureColor.w);\n" + + "}"; + + private int uniformThresholdLocation; + private float threshold; + + public GPUImageLuminanceThresholdFilter() { + this(0.5f); + } + + public GPUImageLuminanceThresholdFilter(float threshold) { + super(NO_FILTER_VERTEX_SHADER, LUMINANCE_THRESHOLD_FRAGMENT_SHADER); + this.threshold = threshold; + } + + @Override + public void onInit() { + super.onInit(); + uniformThresholdLocation = GLES20.glGetUniformLocation(getProgram(), "threshold"); + } + + @Override + public void onInitialized() { + super.onInitialized(); + setThreshold(threshold); + } + + public void setThreshold(final float threshold) { + this.threshold = threshold; + setFloat(uniformThresholdLocation, threshold); + } +} diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageLuminosityBlendFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageLuminosityBlendFilter.java similarity index 96% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageLuminosityBlendFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageLuminosityBlendFilter.java index 85e7bfdae..022f66457 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageLuminosityBlendFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageLuminosityBlendFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; public class GPUImageLuminosityBlendFilter extends GPUImageTwoInputFilter { public static final String LUMINOSITY_BLEND_FRAGMENT_SHADER = "varying highp vec2 textureCoordinate;\n" + diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageMixBlendFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageMixBlendFilter.java similarity index 78% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageMixBlendFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageMixBlendFilter.java index 7bf688590..d04177f07 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageMixBlendFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageMixBlendFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,14 +14,14 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; import android.opengl.GLES20; public class GPUImageMixBlendFilter extends GPUImageTwoInputFilter { - private int mMixLocation; - private float mMix; + private int mixLocation; + private float mix; public GPUImageMixBlendFilter(String fragmentShader) { this(fragmentShader, 0.5f); @@ -29,26 +29,26 @@ public GPUImageMixBlendFilter(String fragmentShader) { public GPUImageMixBlendFilter(String fragmentShader, float mix) { super(fragmentShader); - mMix = mix; + this.mix = mix; } @Override public void onInit() { super.onInit(); - mMixLocation = GLES20.glGetUniformLocation(getProgram(), "mixturePercent"); + mixLocation = GLES20.glGetUniformLocation(getProgram(), "mixturePercent"); } @Override public void onInitialized() { super.onInitialized(); - setMix(mMix); + setMix(mix); } /** * @param mix ranges from 0.0 (only image 1) to 1.0 (only image 2), with 0.5 (half of either) as the normal level */ public void setMix(final float mix) { - mMix = mix; - setFloat(mMixLocation, mMix); + this.mix = mix; + setFloat(mixLocation, this.mix); } } diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageMonochromeFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageMonochromeFilter.java similarity index 78% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageMonochromeFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageMonochromeFilter.java index e426a340c..30525b3f0 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageMonochromeFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageMonochromeFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; import android.opengl.GLES20; @@ -55,47 +55,47 @@ public class GPUImageMonochromeFilter extends GPUImageFilter { " gl_FragColor = vec4( mix(textureColor.rgb, outputColor.rgb, intensity), textureColor.a);\n" + " }"; - private int mIntensityLocation; - private float mIntensity; - private int mFilterColorLocation; - private float[] mColor; + private int intensityLocation; + private float intensity; + private int filterColorLocation; + private float[] color; public GPUImageMonochromeFilter() { - this(1.0f, new float[] {0.6f, 0.45f, 0.3f, 1.0f}); + this(1.0f, new float[]{0.6f, 0.45f, 0.3f, 1.0f}); } public GPUImageMonochromeFilter(final float intensity, final float[] color) { super(NO_FILTER_VERTEX_SHADER, MONOCHROME_FRAGMENT_SHADER); - mIntensity = intensity; - mColor = color; + this.intensity = intensity; + this.color = color; } @Override public void onInit() { super.onInit(); - mIntensityLocation = GLES20.glGetUniformLocation(getProgram(), "intensity"); - mFilterColorLocation = GLES20.glGetUniformLocation(getProgram(), "filterColor"); + intensityLocation = GLES20.glGetUniformLocation(getProgram(), "intensity"); + filterColorLocation = GLES20.glGetUniformLocation(getProgram(), "filterColor"); } @Override public void onInitialized() { super.onInitialized(); setIntensity(1.0f); - setColor(new float[]{ 0.6f, 0.45f, 0.3f, 1.f }); + setColor(new float[]{0.6f, 0.45f, 0.3f, 1.f}); } public void setIntensity(final float intensity) { - mIntensity = intensity; - setFloat(mIntensityLocation, mIntensity); + this.intensity = intensity; + setFloat(intensityLocation, this.intensity); } - + public void setColor(final float[] color) { - mColor = color; - setColorRed(mColor[0], mColor[1], mColor[2]); - + this.color = color; + setColor(this.color[0], this.color[1], this.color[2]); + } - - public void setColorRed(final float red, final float green, final float blue) { - setFloatVec3(mFilterColorLocation, new float[]{ red, green, blue }); + + public void setColor(final float red, final float green, final float blue) { + setFloatVec3(filterColorLocation, new float[]{red, green, blue}); } } diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageMultiplyBlendFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageMultiplyBlendFilter.java similarity index 94% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageMultiplyBlendFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageMultiplyBlendFilter.java index 1e002e367..c5ea9ae8d 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageMultiplyBlendFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageMultiplyBlendFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; public class GPUImageMultiplyBlendFilter extends GPUImageTwoInputFilter { public static final String MULTIPLY_BLEND_FRAGMENT_SHADER = "varying highp vec2 textureCoordinate;\n" + diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageNonMaximumSuppressionFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageNonMaximumSuppressionFilter.java similarity index 97% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageNonMaximumSuppressionFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageNonMaximumSuppressionFilter.java index a6f5af486..239ba9350 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageNonMaximumSuppressionFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageNonMaximumSuppressionFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; public class GPUImageNonMaximumSuppressionFilter extends GPUImage3x3TextureSamplingFilter { public static final String NMS_FRAGMENT_SHADER = "" + diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageNormalBlendFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageNormalBlendFilter.java similarity index 95% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageNormalBlendFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageNormalBlendFilter.java index a886bd407..ced5d1a04 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageNormalBlendFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageNormalBlendFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,19 +14,19 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; /** * This equation is a simplification of the general blending equation. It assumes the destination color is opaque, and therefore drops the destination color's alpha term. - * + *

* D = C1 * C1a + C2 * C2a * (1 - C1a) * where D is the resultant color, C1 is the color of the first element, C1a is the alpha of the first element, C2 is the second element color, C2a is the alpha of the second element. The destination alpha is calculated with: - * + *

* Da = C1a + C2a * (1 - C1a) * The resultant color is premultiplied with the alpha. To restore the color to the unmultiplied values, just divide by Da, the resultant alpha. - * + *

* http://stackoverflow.com/questions/1724946/blend-mode-on-a-transparent-and-semi-transparent-background - * + *

* For some reason Photoshop behaves * D = C1 + C2 * C2a * (1 - C1a) */ diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageOpacityFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageOpacityFilter.java similarity index 82% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageOpacityFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageOpacityFilter.java index 55f198d14..4eb1cf79a 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageOpacityFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageOpacityFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,14 +14,14 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; import android.opengl.GLES20; /** * Adjusts the alpha channel of the incoming image * opacity: The value to multiply the incoming alpha channel for each pixel by (0.0 - 1.0, with 1.0 as the default) -*/ + */ public class GPUImageOpacityFilter extends GPUImageFilter { public static final String OPACITY_FRAGMENT_SHADER = "" + " varying highp vec2 textureCoordinate;\n" + @@ -36,8 +36,8 @@ public class GPUImageOpacityFilter extends GPUImageFilter { " gl_FragColor = vec4(textureColor.rgb, textureColor.a * opacity);\n" + " }\n"; - private int mOpacityLocation; - private float mOpacity; + private int opacityLocation; + private float opacity; public GPUImageOpacityFilter() { this(1.0f); @@ -45,23 +45,23 @@ public GPUImageOpacityFilter() { public GPUImageOpacityFilter(final float opacity) { super(NO_FILTER_VERTEX_SHADER, OPACITY_FRAGMENT_SHADER); - mOpacity = opacity; + this.opacity = opacity; } @Override public void onInit() { super.onInit(); - mOpacityLocation = GLES20.glGetUniformLocation(getProgram(), "opacity"); + opacityLocation = GLES20.glGetUniformLocation(getProgram(), "opacity"); } @Override public void onInitialized() { super.onInitialized(); - setOpacity(mOpacity); + setOpacity(opacity); } public void setOpacity(final float opacity) { - mOpacity = opacity; - setFloat(mOpacityLocation, mOpacity); + this.opacity = opacity; + setFloat(opacityLocation, this.opacity); } } diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageOverlayBlendFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageOverlayBlendFilter.java similarity index 96% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageOverlayBlendFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageOverlayBlendFilter.java index 4dba4200c..3d36b1879 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageOverlayBlendFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageOverlayBlendFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; public class GPUImageOverlayBlendFilter extends GPUImageTwoInputFilter { public static final String OVERLAY_BLEND_FRAGMENT_SHADER = "varying highp vec2 textureCoordinate;\n" + diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImagePixelationFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImagePixelationFilter.java similarity index 69% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImagePixelationFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImagePixelationFilter.java index c0ec15d13..0e061bfdd 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImagePixelationFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImagePixelationFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,9 +14,10 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; import android.opengl.GLES20; + /** * Applies a grayscale effect to the image. */ @@ -41,34 +42,39 @@ public class GPUImagePixelationFilter extends GPUImageFilter { " gl_FragColor = vec4(tc, 1.0);\n" + "}"; - private int mImageWidthFactorLocation; - private int mImageHeightFactorLocation; - private float mPixel; - private int mPixelLocation; - + private int imageWidthFactorLocation; + private int imageHeightFactorLocation; + private float pixel; + private int pixelLocation; + public GPUImagePixelationFilter() { super(NO_FILTER_VERTEX_SHADER, PIXELATION_FRAGMENT_SHADER); - mPixel = 1.0f; + pixel = 1.0f; } @Override public void onInit() { super.onInit(); - mImageWidthFactorLocation = GLES20.glGetUniformLocation(getProgram(), "imageWidthFactor"); - mImageHeightFactorLocation = GLES20.glGetUniformLocation(getProgram(), "imageHeightFactor"); - mPixelLocation = GLES20.glGetUniformLocation(getProgram(), "pixel"); - setPixel(mPixel); + imageWidthFactorLocation = GLES20.glGetUniformLocation(getProgram(), "imageWidthFactor"); + imageHeightFactorLocation = GLES20.glGetUniformLocation(getProgram(), "imageHeightFactor"); + pixelLocation = GLES20.glGetUniformLocation(getProgram(), "pixel"); + } + + @Override + public void onInitialized() { + super.onInitialized(); + setPixel(pixel); } @Override public void onOutputSizeChanged(final int width, final int height) { super.onOutputSizeChanged(width, height); - setFloat(mImageWidthFactorLocation, 1.0f / width); - setFloat(mImageHeightFactorLocation, 1.0f / height); + setFloat(imageWidthFactorLocation, 1.0f / width); + setFloat(imageHeightFactorLocation, 1.0f / height); } public void setPixel(final float pixel) { - mPixel = pixel; - setFloat(mPixelLocation, mPixel); + this.pixel = pixel; + setFloat(pixelLocation, this.pixel); } } diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImagePosterizeFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImagePosterizeFilter.java similarity index 76% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImagePosterizeFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImagePosterizeFilter.java index 3b7c8ff7b..885b4e7d9 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImagePosterizeFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImagePosterizeFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; import android.opengl.GLES20; @@ -37,8 +37,8 @@ public class GPUImagePosterizeFilter extends GPUImageFilter { " gl_FragColor = floor((textureColor * colorLevels) + vec4(0.5)) / colorLevels;\n" + "}"; - private int mGLUniformColorLevels; - private int mColorLevels; + private int glUniformColorLevels; + private int colorLevels; public GPUImagePosterizeFilter() { this(10); @@ -46,18 +46,23 @@ public GPUImagePosterizeFilter() { public GPUImagePosterizeFilter(final int colorLevels) { super(GPUImageFilter.NO_FILTER_VERTEX_SHADER, POSTERIZE_FRAGMENT_SHADER); - mColorLevels = colorLevels; + this.colorLevels = colorLevels; } @Override public void onInit() { super.onInit(); - mGLUniformColorLevels = GLES20.glGetUniformLocation(getProgram(), "colorLevels"); - setColorLevels(mColorLevels); + glUniformColorLevels = GLES20.glGetUniformLocation(getProgram(), "colorLevels"); + } + + @Override + public void onInitialized() { + super.onInitialized(); + setColorLevels(colorLevels); } public void setColorLevels(final int colorLevels) { - mColorLevels = colorLevels; - setFloat(mGLUniformColorLevels, colorLevels); + this.colorLevels = colorLevels; + setFloat(glUniformColorLevels, colorLevels); } } diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageRGBDilationFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageRGBDilationFilter.java similarity index 99% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageRGBDilationFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageRGBDilationFilter.java index 2d5e28c78..cb777767e 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageRGBDilationFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageRGBDilationFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; /** * For each pixel, this sets it to the maximum value of each color channel in a rectangular neighborhood extending diff --git a/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageRGBFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageRGBFilter.java new file mode 100644 index 000000000..25889f375 --- /dev/null +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageRGBFilter.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2018 CyberAgent, Inc. + * + * 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 jp.co.cyberagent.android.gpuimage.filter; + +import android.opengl.GLES20; + +/** + * Adjusts the individual RGB channels of an image + * red: Normalized values by which each color channel is multiplied. The range is from 0.0 up, with 1.0 as the default. + * green: + * blue: + */ +public class GPUImageRGBFilter extends GPUImageFilter { + public static final String RGB_FRAGMENT_SHADER = "" + + " varying highp vec2 textureCoordinate;\n" + + " \n" + + " uniform sampler2D inputImageTexture;\n" + + " uniform highp float red;\n" + + " uniform highp float green;\n" + + " uniform highp float blue;\n" + + " \n" + + " void main()\n" + + " {\n" + + " highp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);\n" + + " \n" + + " gl_FragColor = vec4(textureColor.r * red, textureColor.g * green, textureColor.b * blue, 1.0);\n" + + " }\n"; + + private int redLocation; + private float red; + private int greenLocation; + private float green; + private int blueLocation; + private float blue; + + public GPUImageRGBFilter() { + this(1.0f, 1.0f, 1.0f); + } + + public GPUImageRGBFilter(final float red, final float green, final float blue) { + super(NO_FILTER_VERTEX_SHADER, RGB_FRAGMENT_SHADER); + this.red = red; + this.green = green; + this.blue = blue; + } + + @Override + public void onInit() { + super.onInit(); + redLocation = GLES20.glGetUniformLocation(getProgram(), "red"); + greenLocation = GLES20.glGetUniformLocation(getProgram(), "green"); + blueLocation = GLES20.glGetUniformLocation(getProgram(), "blue"); + } + + @Override + public void onInitialized() { + super.onInitialized(); + setRed(red); + setGreen(green); + setBlue(blue); + } + + public void setRed(final float red) { + this.red = red; + setFloat(redLocation, this.red); + } + + public void setGreen(final float green) { + this.green = green; + setFloat(greenLocation, this.green); + } + + public void setBlue(final float blue) { + this.blue = blue; + setFloat(blueLocation, this.blue); + } +} diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageSaturationBlendFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSaturationBlendFilter.java similarity index 98% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageSaturationBlendFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSaturationBlendFilter.java index 1c0f90d68..eacb809ec 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageSaturationBlendFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSaturationBlendFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; public class GPUImageSaturationBlendFilter extends GPUImageTwoInputFilter { public static final String SATURATION_BLEND_FRAGMENT_SHADER = "varying highp vec2 textureCoordinate;\n" + diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageSaturationFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSaturationFilter.java similarity index 84% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageSaturationFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSaturationFilter.java index 0725953d3..dd1f59ce0 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageSaturationFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSaturationFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; import android.opengl.GLES20; @@ -41,8 +41,8 @@ public class GPUImageSaturationFilter extends GPUImageFilter { " \n" + " }"; - private int mSaturationLocation; - private float mSaturation; + private int saturationLocation; + private float saturation; public GPUImageSaturationFilter() { this(1.0f); @@ -50,23 +50,23 @@ public GPUImageSaturationFilter() { public GPUImageSaturationFilter(final float saturation) { super(NO_FILTER_VERTEX_SHADER, SATURATION_FRAGMENT_SHADER); - mSaturation = saturation; + this.saturation = saturation; } @Override public void onInit() { super.onInit(); - mSaturationLocation = GLES20.glGetUniformLocation(getProgram(), "saturation"); + saturationLocation = GLES20.glGetUniformLocation(getProgram(), "saturation"); } @Override public void onInitialized() { super.onInitialized(); - setSaturation(mSaturation); + setSaturation(saturation); } public void setSaturation(final float saturation) { - mSaturation = saturation; - setFloat(mSaturationLocation, mSaturation); + this.saturation = saturation; + setFloat(saturationLocation, this.saturation); } } diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageScreenBlendFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageScreenBlendFilter.java similarity index 94% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageScreenBlendFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageScreenBlendFilter.java index 2c63a6992..56ba3db1d 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageScreenBlendFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageScreenBlendFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; public class GPUImageScreenBlendFilter extends GPUImageTwoInputFilter { public static final String SCREEN_BLEND_FRAGMENT_SHADER = "varying highp vec2 textureCoordinate;\n" + diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageSepiaFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSepiaToneFilter.java similarity index 73% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageSepiaFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSepiaToneFilter.java index cbcf35346..cbad3d2ef 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageSepiaFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSepiaToneFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,19 +14,19 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; /** * Applies a simple sepia effect. */ -public class GPUImageSepiaFilter extends GPUImageColorMatrixFilter { +public class GPUImageSepiaToneFilter extends GPUImageColorMatrixFilter { - public GPUImageSepiaFilter() { + public GPUImageSepiaToneFilter() { this(1.0f); } - public GPUImageSepiaFilter(final float intensity) { - super(intensity, new float[] { + public GPUImageSepiaToneFilter(final float intensity) { + super(intensity, new float[]{ 0.3588f, 0.7044f, 0.1368f, 0.0f, 0.2990f, 0.5870f, 0.1140f, 0.0f, 0.2392f, 0.4696f, 0.0912f, 0.0f, diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageSharpenFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSharpenFilter.java similarity index 66% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageSharpenFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSharpenFilter.java index 4317b66c6..c0cf6820d 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageSharpenFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSharpenFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; import android.opengl.GLES20; @@ -59,62 +59,67 @@ public class GPUImageSharpenFilter extends GPUImageFilter { "}"; public static final String SHARPEN_FRAGMENT_SHADER = "" + - "precision highp float;\n" + - "\n" + - "varying highp vec2 textureCoordinate;\n" + - "varying highp vec2 leftTextureCoordinate;\n" + - "varying highp vec2 rightTextureCoordinate; \n" + - "varying highp vec2 topTextureCoordinate;\n" + - "varying highp vec2 bottomTextureCoordinate;\n" + - "\n" + - "varying highp float centerMultiplier;\n" + - "varying highp float edgeMultiplier;\n" + - "\n" + - "uniform sampler2D inputImageTexture;\n" + - "\n" + - "void main()\n" + - "{\n" + - " mediump vec3 textureColor = texture2D(inputImageTexture, textureCoordinate).rgb;\n" + - " mediump vec3 leftTextureColor = texture2D(inputImageTexture, leftTextureCoordinate).rgb;\n" + - " mediump vec3 rightTextureColor = texture2D(inputImageTexture, rightTextureCoordinate).rgb;\n" + - " mediump vec3 topTextureColor = texture2D(inputImageTexture, topTextureCoordinate).rgb;\n" + - " mediump vec3 bottomTextureColor = texture2D(inputImageTexture, bottomTextureCoordinate).rgb;\n" + - "\n" + - " gl_FragColor = vec4((textureColor * centerMultiplier - (leftTextureColor * edgeMultiplier + rightTextureColor * edgeMultiplier + topTextureColor * edgeMultiplier + bottomTextureColor * edgeMultiplier)), texture2D(inputImageTexture, bottomTextureCoordinate).w);\n" + + "precision highp float;\n" + + "\n" + + "varying highp vec2 textureCoordinate;\n" + + "varying highp vec2 leftTextureCoordinate;\n" + + "varying highp vec2 rightTextureCoordinate; \n" + + "varying highp vec2 topTextureCoordinate;\n" + + "varying highp vec2 bottomTextureCoordinate;\n" + + "\n" + + "varying highp float centerMultiplier;\n" + + "varying highp float edgeMultiplier;\n" + + "\n" + + "uniform sampler2D inputImageTexture;\n" + + "\n" + + "void main()\n" + + "{\n" + + " mediump vec3 textureColor = texture2D(inputImageTexture, textureCoordinate).rgb;\n" + + " mediump vec3 leftTextureColor = texture2D(inputImageTexture, leftTextureCoordinate).rgb;\n" + + " mediump vec3 rightTextureColor = texture2D(inputImageTexture, rightTextureCoordinate).rgb;\n" + + " mediump vec3 topTextureColor = texture2D(inputImageTexture, topTextureCoordinate).rgb;\n" + + " mediump vec3 bottomTextureColor = texture2D(inputImageTexture, bottomTextureCoordinate).rgb;\n" + + "\n" + + " gl_FragColor = vec4((textureColor * centerMultiplier - (leftTextureColor * edgeMultiplier + rightTextureColor * edgeMultiplier + topTextureColor * edgeMultiplier + bottomTextureColor * edgeMultiplier)), texture2D(inputImageTexture, bottomTextureCoordinate).w);\n" + "}"; - private int mSharpnessLocation; - private float mSharpness; - private int mImageWidthFactorLocation; - private int mImageHeightFactorLocation; + private int sharpnessLocation; + private float sharpness; + private int imageWidthFactorLocation; + private int imageHeightFactorLocation; public GPUImageSharpenFilter() { this(0.0f); } - + public GPUImageSharpenFilter(final float sharpness) { super(SHARPEN_VERTEX_SHADER, SHARPEN_FRAGMENT_SHADER); - mSharpness = sharpness; + this.sharpness = sharpness; } @Override public void onInit() { super.onInit(); - mSharpnessLocation = GLES20.glGetUniformLocation(getProgram(), "sharpness"); - mImageWidthFactorLocation = GLES20.glGetUniformLocation(getProgram(), "imageWidthFactor"); - mImageHeightFactorLocation = GLES20.glGetUniformLocation(getProgram(), "imageHeightFactor"); - setSharpness(mSharpness); + sharpnessLocation = GLES20.glGetUniformLocation(getProgram(), "sharpness"); + imageWidthFactorLocation = GLES20.glGetUniformLocation(getProgram(), "imageWidthFactor"); + imageHeightFactorLocation = GLES20.glGetUniformLocation(getProgram(), "imageHeightFactor"); + } + + @Override + public void onInitialized() { + super.onInitialized(); + setSharpness(sharpness); } @Override public void onOutputSizeChanged(final int width, final int height) { super.onOutputSizeChanged(width, height); - setFloat(mImageWidthFactorLocation, 1.0f / width); - setFloat(mImageHeightFactorLocation, 1.0f / height); + setFloat(imageWidthFactorLocation, 1.0f / width); + setFloat(imageHeightFactorLocation, 1.0f / height); } public void setSharpness(final float sharpness) { - mSharpness = sharpness; - setFloat(mSharpnessLocation, mSharpness); + this.sharpness = sharpness; + setFloat(sharpnessLocation, this.sharpness); } } diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageSketchFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSketchFilter.java similarity index 95% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageSketchFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSketchFilter.java index dd78e7085..905d20d9a 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageSketchFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSketchFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,10 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; - -import java.util.ArrayList; -import java.util.List; +package jp.co.cyberagent.android.gpuimage.filter; /** * Converts video to look like a sketch. diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageSmoothToonFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSmoothToonFilter.java similarity index 80% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageSmoothToonFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSmoothToonFilter.java index a569ce972..079034d4e 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageSmoothToonFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSmoothToonFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,17 +14,16 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; - -import android.opengl.GLES20; +package jp.co.cyberagent.android.gpuimage.filter; /** - * This uses a similar process as the GPUImageToonFilter, only it precedes the toon effect - * with a Gaussian blur to smooth out noise. + * This uses a similar process as the GPUImageToonFilter, only it precedes the toon effect + * with a Gaussian blur to smooth out noise. */ public class GPUImageSmoothToonFilter extends GPUImageFilterGroup { - GPUImageGaussianBlurFilter blurFilter; - GPUImageToonFilter toonFilter; + + private GPUImageGaussianBlurFilter blurFilter; + private GPUImageToonFilter toonFilter; /** * Setup and Tear down @@ -39,7 +38,11 @@ public GPUImageSmoothToonFilter() { addFilter(toonFilter); getFilters().add(blurFilter); + } + @Override + public void onInitialized() { + super.onInitialized(); setBlurSize(0.5f); setThreshold(0.2f); setQuantizationLevels(10.0f); diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageSobelEdgeDetection.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSobelEdgeDetectionFilter.java similarity index 52% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageSobelEdgeDetection.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSobelEdgeDetectionFilter.java index 2a775d483..b7482486e 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageSobelEdgeDetection.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSobelEdgeDetectionFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,51 +14,48 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; - -import java.util.ArrayList; -import java.util.List; +package jp.co.cyberagent.android.gpuimage.filter; /** * Applies sobel edge detection on the image. */ -public class GPUImageSobelEdgeDetection extends GPUImageFilterGroup { +public class GPUImageSobelEdgeDetectionFilter extends GPUImageFilterGroup { public static final String SOBEL_EDGE_DETECTION = "" + - "precision mediump float;\n" + - "\n" + - "varying vec2 textureCoordinate;\n" + - "varying vec2 leftTextureCoordinate;\n" + - "varying vec2 rightTextureCoordinate;\n" + - "\n" + - "varying vec2 topTextureCoordinate;\n" + - "varying vec2 topLeftTextureCoordinate;\n" + - "varying vec2 topRightTextureCoordinate;\n" + - "\n" + - "varying vec2 bottomTextureCoordinate;\n" + - "varying vec2 bottomLeftTextureCoordinate;\n" + - "varying vec2 bottomRightTextureCoordinate;\n" + - "\n" + - "uniform sampler2D inputImageTexture;\n" + - "\n" + - "void main()\n" + - "{\n" + - " float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r;\n" + - " float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r;\n" + - " float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r;\n" + - " float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r;\n" + - " float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r;\n" + - " float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r;\n" + - " float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r;\n" + - " float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r;\n" + - " float h = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + bottomLeftIntensity + 2.0 * bottomIntensity + bottomRightIntensity;\n" + - " float v = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomRightIntensity + 2.0 * rightIntensity + topRightIntensity;\n" + - "\n" + - " float mag = length(vec2(h, v));\n" + - "\n" + - " gl_FragColor = vec4(vec3(mag), 1.0);\n" + + "precision mediump float;\n" + + "\n" + + "varying vec2 textureCoordinate;\n" + + "varying vec2 leftTextureCoordinate;\n" + + "varying vec2 rightTextureCoordinate;\n" + + "\n" + + "varying vec2 topTextureCoordinate;\n" + + "varying vec2 topLeftTextureCoordinate;\n" + + "varying vec2 topRightTextureCoordinate;\n" + + "\n" + + "varying vec2 bottomTextureCoordinate;\n" + + "varying vec2 bottomLeftTextureCoordinate;\n" + + "varying vec2 bottomRightTextureCoordinate;\n" + + "\n" + + "uniform sampler2D inputImageTexture;\n" + + "\n" + + "void main()\n" + + "{\n" + + " float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r;\n" + + " float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r;\n" + + " float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r;\n" + + " float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r;\n" + + " float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r;\n" + + " float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r;\n" + + " float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r;\n" + + " float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r;\n" + + " float h = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + bottomLeftIntensity + 2.0 * bottomIntensity + bottomRightIntensity;\n" + + " float v = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomRightIntensity + 2.0 * rightIntensity + topRightIntensity;\n" + + "\n" + + " float mag = length(vec2(h, v));\n" + + "\n" + + " gl_FragColor = vec4(vec3(mag), 1.0);\n" + "}"; - public GPUImageSobelEdgeDetection() { + public GPUImageSobelEdgeDetectionFilter() { super(); addFilter(new GPUImageGrayscaleFilter()); addFilter(new GPUImage3x3TextureSamplingFilter(SOBEL_EDGE_DETECTION)); diff --git a/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSobelThresholdFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSobelThresholdFilter.java new file mode 100644 index 000000000..beff588c8 --- /dev/null +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSobelThresholdFilter.java @@ -0,0 +1,74 @@ +package jp.co.cyberagent.android.gpuimage.filter; + +import android.opengl.GLES20; + +public class GPUImageSobelThresholdFilter extends + GPUImage3x3TextureSamplingFilter { + public static final String SOBEL_THRESHOLD_EDGE_DETECTION = "" + + "precision mediump float;\n" + + "\n" + + "varying vec2 textureCoordinate;\n" + + "varying vec2 leftTextureCoordinate;\n" + + "varying vec2 rightTextureCoordinate;\n" + + "\n" + + "varying vec2 topTextureCoordinate;\n" + + "varying vec2 topLeftTextureCoordinate;\n" + + "varying vec2 topRightTextureCoordinate;\n" + + "\n" + + "varying vec2 bottomTextureCoordinate;\n" + + "varying vec2 bottomLeftTextureCoordinate;\n" + + "varying vec2 bottomRightTextureCoordinate;\n" + + "\n" + + "uniform sampler2D inputImageTexture;\n" + + "uniform lowp float threshold;\n" + + "\n" + + "const highp vec3 W = vec3(0.2125, 0.7154, 0.0721);\n" + + "\n" + + "void main()\n" + + "{\n" + + " float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r;\n" + + " float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r;\n" + + " float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r;\n" + + " float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r;\n" + + " float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r;\n" + + " float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r;\n" + + " float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r;\n" + + " float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r;\n" + + " float h = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + bottomLeftIntensity + 2.0 * bottomIntensity + bottomRightIntensity;\n" + + " float v = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomRightIntensity + 2.0 * rightIntensity + topRightIntensity;\n" + + "\n" + + " float mag = 1.0 - length(vec2(h, v));\n" + + " mag = step(threshold, mag);\n" + + "\n" + + " gl_FragColor = vec4(vec3(mag), 1.0);\n" + + "}\n"; + + private int uniformThresholdLocation; + private float threshold; + + public GPUImageSobelThresholdFilter() { + this(0.9f); + } + + public GPUImageSobelThresholdFilter(float threshold) { + super(SOBEL_THRESHOLD_EDGE_DETECTION); + this.threshold = threshold; + } + + @Override + public void onInit() { + super.onInit(); + uniformThresholdLocation = GLES20.glGetUniformLocation(getProgram(), "threshold"); + } + + @Override + public void onInitialized() { + super.onInitialized(); + setThreshold(threshold); + } + + public void setThreshold(final float threshold) { + this.threshold = threshold; + setFloat(uniformThresholdLocation, threshold); + } +} diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageSoftLightBlendFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSoftLightBlendFilter.java similarity index 94% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageSoftLightBlendFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSoftLightBlendFilter.java index 0e1b742e6..1310f3fb1 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageSoftLightBlendFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSoftLightBlendFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; public class GPUImageSoftLightBlendFilter extends GPUImageTwoInputFilter { public static final String SOFT_LIGHT_BLEND_FRAGMENT_SHADER = "varying highp vec2 textureCoordinate;\n" + diff --git a/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSolarizeFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSolarizeFilter.java new file mode 100644 index 000000000..ee63cdd87 --- /dev/null +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSolarizeFilter.java @@ -0,0 +1,52 @@ +package jp.co.cyberagent.android.gpuimage.filter; + +import android.opengl.GLES20; + +public class GPUImageSolarizeFilter extends GPUImageFilter { + public static final String SOLATIZE_FRAGMENT_SHADER = "" + + "varying highp vec2 textureCoordinate;\n" + + "\n" + + "uniform sampler2D inputImageTexture;\n" + + "uniform highp float threshold;\n" + + "\n" + + "const highp vec3 W = vec3(0.2125, 0.7154, 0.0721);\n" + + "\n" + + "void main()\n" + + "{\n" + + " highp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);\n" + + " highp float luminance = dot(textureColor.rgb, W);\n" + + " highp float thresholdResult = step(luminance, threshold);\n" + + " highp vec3 finalColor = abs(thresholdResult - textureColor.rgb);\n" + + " \n" + + " gl_FragColor = vec4(finalColor, textureColor.w);\n" + + "}"; + + private int uniformThresholdLocation; + private float threshold; + + public GPUImageSolarizeFilter() { + this(0.5f); + } + + public GPUImageSolarizeFilter(float threshold) { + super(NO_FILTER_VERTEX_SHADER, SOLATIZE_FRAGMENT_SHADER); + this.threshold = threshold; + } + + @Override + public void onInit() { + super.onInit(); + uniformThresholdLocation = GLES20.glGetUniformLocation(getProgram(), "threshold"); + } + + @Override + public void onInitialized() { + super.onInitialized(); + setThreshold(threshold); + } + + public void setThreshold(final float threshold) { + this.threshold = threshold; + setFloat(uniformThresholdLocation, threshold); + } +} diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageSourceOverBlendFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSourceOverBlendFilter.java similarity index 94% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageSourceOverBlendFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSourceOverBlendFilter.java index fd6a7b986..aa175b603 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageSourceOverBlendFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSourceOverBlendFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; public class GPUImageSourceOverBlendFilter extends GPUImageTwoInputFilter { public static final String SOURCE_OVER_BLEND_FRAGMENT_SHADER = "varying highp vec2 textureCoordinate;\n" + diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageSphereRefractionFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSphereRefractionFilter.java similarity index 71% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageSphereRefractionFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSphereRefractionFilter.java index 6314cf196..f0ffecccf 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageSphereRefractionFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSphereRefractionFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; import android.graphics.PointF; import android.opengl.GLES20; @@ -46,14 +46,14 @@ public class GPUImageSphereRefractionFilter extends GPUImageFilter { "gl_FragColor = texture2D(inputImageTexture, (refractedVector.xy + 1.0) * 0.5) * checkForPresenceWithinSphere; \n" + "}\n"; - private PointF mCenter; - private int mCenterLocation; - private float mRadius; - private int mRadiusLocation; - private float mAspectRatio; - private int mAspectRatioLocation; - private float mRefractiveIndex; - private int mRefractiveIndexLocation; + private PointF center; + private int centerLocation; + private float radius; + private int radiusLocation; + private float aspectRatio; + private int aspectRatioLocation; + private float refractiveIndex; + private int refractiveIndexLocation; public GPUImageSphereRefractionFilter() { this(new PointF(0.5f, 0.5f), 0.25f, 0.71f); @@ -61,38 +61,39 @@ public GPUImageSphereRefractionFilter() { public GPUImageSphereRefractionFilter(PointF center, float radius, float refractiveIndex) { super(NO_FILTER_VERTEX_SHADER, SPHERE_FRAGMENT_SHADER); - mCenter = center; - mRadius = radius; - mRefractiveIndex = refractiveIndex; + this.center = center; + this.radius = radius; + this.refractiveIndex = refractiveIndex; } @Override public void onInit() { super.onInit(); - mCenterLocation = GLES20.glGetUniformLocation(getProgram(), "center"); - mRadiusLocation = GLES20.glGetUniformLocation(getProgram(), "radius"); - mAspectRatioLocation = GLES20.glGetUniformLocation(getProgram(), "aspectRatio"); - mRefractiveIndexLocation = GLES20.glGetUniformLocation(getProgram(), "refractiveIndex"); + centerLocation = GLES20.glGetUniformLocation(getProgram(), "center"); + radiusLocation = GLES20.glGetUniformLocation(getProgram(), "radius"); + aspectRatioLocation = GLES20.glGetUniformLocation(getProgram(), "aspectRatio"); + refractiveIndexLocation = GLES20.glGetUniformLocation(getProgram(), "refractiveIndex"); } @Override public void onInitialized() { super.onInitialized(); - setRadius(mRadius); - setCenter(mCenter); - setRefractiveIndex(mRefractiveIndex); + setAspectRatio(aspectRatio); + setRadius(radius); + setCenter(center); + setRefractiveIndex(refractiveIndex); } @Override public void onOutputSizeChanged(int width, int height) { - mAspectRatio = (float) height / width; - setAspectRatio(mAspectRatio); + aspectRatio = (float) height / width; + setAspectRatio(aspectRatio); super.onOutputSizeChanged(width, height); } private void setAspectRatio(float aspectRatio) { - mAspectRatio = aspectRatio; - setFloat(mAspectRatioLocation, aspectRatio); + this.aspectRatio = aspectRatio; + setFloat(aspectRatioLocation, aspectRatio); } /** @@ -101,8 +102,8 @@ private void setAspectRatio(float aspectRatio) { * @param refractiveIndex default 0.71 */ public void setRefractiveIndex(float refractiveIndex) { - mRefractiveIndex = refractiveIndex; - setFloat(mRefractiveIndexLocation, refractiveIndex); + this.refractiveIndex = refractiveIndex; + setFloat(refractiveIndexLocation, refractiveIndex); } /** @@ -111,8 +112,8 @@ public void setRefractiveIndex(float refractiveIndex) { * @param center default (0.5, 0.5) */ public void setCenter(PointF center) { - mCenter = center; - setPoint(mCenterLocation, center); + this.center = center; + setPoint(centerLocation, center); } /** @@ -121,7 +122,7 @@ public void setCenter(PointF center) { * @param radius from 0.0 to 1.0, default 0.25 */ public void setRadius(float radius) { - mRadius = radius; - setFloat(mRadiusLocation, radius); + this.radius = radius; + setFloat(radiusLocation, radius); } } diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageSubtractBlendFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSubtractBlendFilter.java similarity index 94% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageSubtractBlendFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSubtractBlendFilter.java index 52b54ecc7..0aec1891f 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageSubtractBlendFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSubtractBlendFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; public class GPUImageSubtractBlendFilter extends GPUImageTwoInputFilter { public static final String SUBTRACT_BLEND_FRAGMENT_SHADER = "varying highp vec2 textureCoordinate;\n" + diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageSwirlFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSwirlFilter.java similarity index 77% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageSwirlFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSwirlFilter.java index d4947b9af..e35698ca8 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageSwirlFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageSwirlFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; import android.graphics.PointF; import android.opengl.GLES20; @@ -51,12 +51,12 @@ public class GPUImageSwirlFilter extends GPUImageFilter { "\n" + "}\n"; - private float mAngle; - private int mAngleLocation; - private float mRadius; - private int mRadiusLocation; - private PointF mCenter; - private int mCenterLocation; + private float angle; + private int angleLocation; + private float radius; + private int radiusLocation; + private PointF center; + private int centerLocation; public GPUImageSwirlFilter() { this(0.5f, 1.0f, new PointF(0.5f, 0.5f)); @@ -64,25 +64,25 @@ public GPUImageSwirlFilter() { public GPUImageSwirlFilter(float radius, float angle, PointF center) { super(NO_FILTER_VERTEX_SHADER, SWIRL_FRAGMENT_SHADER); - mRadius = radius; - mAngle = angle; - mCenter = center; + this.radius = radius; + this.angle = angle; + this.center = center; } @Override public void onInit() { super.onInit(); - mAngleLocation = GLES20.glGetUniformLocation(getProgram(), "angle"); - mRadiusLocation = GLES20.glGetUniformLocation(getProgram(), "radius"); - mCenterLocation = GLES20.glGetUniformLocation(getProgram(), "center"); + angleLocation = GLES20.glGetUniformLocation(getProgram(), "angle"); + radiusLocation = GLES20.glGetUniformLocation(getProgram(), "radius"); + centerLocation = GLES20.glGetUniformLocation(getProgram(), "center"); } @Override public void onInitialized() { super.onInitialized(); - setRadius(mRadius); - setAngle(mAngle); - setCenter(mCenter); + setRadius(radius); + setAngle(angle); + setCenter(center); } /** @@ -91,8 +91,8 @@ public void onInitialized() { * @param radius from 0.0 to 1.0, default 0.5 */ public void setRadius(float radius) { - mRadius = radius; - setFloat(mRadiusLocation, radius); + this.radius = radius; + setFloat(radiusLocation, radius); } /** @@ -101,8 +101,8 @@ public void setRadius(float radius) { * @param angle minimum 0.0, default 1.0 */ public void setAngle(float angle) { - mAngle = angle; - setFloat(mAngleLocation, angle); + this.angle = angle; + setFloat(angleLocation, angle); } /** @@ -111,7 +111,7 @@ public void setAngle(float angle) { * @param center default (0.5, 0.5) */ public void setCenter(PointF center) { - mCenter = center; - setPoint(mCenterLocation, center); + this.center = center; + setPoint(centerLocation, center); } } diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageThresholdEdgeDetection.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageThresholdEdgeDetectionFilter.java similarity index 72% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageThresholdEdgeDetection.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageThresholdEdgeDetectionFilter.java index c136155a6..3416e91d6 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageThresholdEdgeDetection.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageThresholdEdgeDetectionFilter.java @@ -1,10 +1,10 @@ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; /** * Applies sobel edge detection on the image. */ -public class GPUImageThresholdEdgeDetection extends GPUImageFilterGroup { - public GPUImageThresholdEdgeDetection() { +public class GPUImageThresholdEdgeDetectionFilter extends GPUImageFilterGroup { + public GPUImageThresholdEdgeDetectionFilter() { super(); addFilter(new GPUImageGrayscaleFilter()); addFilter(new GPUImageSobelThresholdFilter()); diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageToneCurveFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageToneCurveFilter.java similarity index 78% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageToneCurveFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageToneCurveFilter.java index 0f6e1d082..9c5a4f5ad 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageToneCurveFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageToneCurveFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,18 +14,21 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; import android.graphics.Point; import android.graphics.PointF; import android.opengl.GLES20; -import java.io.*; +import java.io.IOException; +import java.io.InputStream; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; +import jp.co.cyberagent.android.gpuimage.util.OpenGlUtils; + public class GPUImageToneCurveFilter extends GPUImageFilter { public static final String TONE_CURVE_FRAGMENT_SHADER = "" + " varying highp vec2 textureCoordinate;\n" + @@ -42,37 +45,37 @@ public class GPUImageToneCurveFilter extends GPUImageFilter { " gl_FragColor = vec4(redCurveValue, greenCurveValue, blueCurveValue, textureColor.a);\n" + " }"; - private int[] mToneCurveTexture = new int[]{OpenGlUtils.NO_TEXTURE}; - private int mToneCurveTextureUniformLocation; + private int[] toneCurveTexture = new int[]{OpenGlUtils.NO_TEXTURE}; + private int toneCurveTextureUniformLocation; - private PointF[] mRgbCompositeControlPoints; - private PointF[] mRedControlPoints; - private PointF[] mGreenControlPoints; - private PointF[] mBlueControlPoints; + private PointF[] rgbCompositeControlPoints; + private PointF[] redControlPoints; + private PointF[] greenControlPoints; + private PointF[] blueControlPoints; - private ArrayList mRgbCompositeCurve; - private ArrayList mRedCurve; - private ArrayList mGreenCurve; - private ArrayList mBlueCurve; + private ArrayList rgbCompositeCurve; + private ArrayList redCurve; + private ArrayList greenCurve; + private ArrayList blueCurve; public GPUImageToneCurveFilter() { super(NO_FILTER_VERTEX_SHADER, TONE_CURVE_FRAGMENT_SHADER); PointF[] defaultCurvePoints = new PointF[]{new PointF(0.0f, 0.0f), new PointF(0.5f, 0.5f), new PointF(1.0f, 1.0f)}; - mRgbCompositeControlPoints = defaultCurvePoints; - mRedControlPoints = defaultCurvePoints; - mGreenControlPoints = defaultCurvePoints; - mBlueControlPoints = defaultCurvePoints; + rgbCompositeControlPoints = defaultCurvePoints; + redControlPoints = defaultCurvePoints; + greenControlPoints = defaultCurvePoints; + blueControlPoints = defaultCurvePoints; } @Override public void onInit() { super.onInit(); - mToneCurveTextureUniformLocation = GLES20.glGetUniformLocation(getProgram(), "toneCurveTexture"); + toneCurveTextureUniformLocation = GLES20.glGetUniformLocation(getProgram(), "toneCurveTexture"); GLES20.glActiveTexture(GLES20.GL_TEXTURE3); - GLES20.glGenTextures(1, mToneCurveTexture, 0); - GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mToneCurveTexture[0]); + GLES20.glGenTextures(1, toneCurveTexture, 0); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, toneCurveTexture[0]); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); @@ -82,18 +85,18 @@ public void onInit() { @Override public void onInitialized() { super.onInitialized(); - setRgbCompositeControlPoints(mRgbCompositeControlPoints); - setRedControlPoints(mRedControlPoints); - setGreenControlPoints(mGreenControlPoints); - setBlueControlPoints(mBlueControlPoints); + setRgbCompositeControlPoints(rgbCompositeControlPoints); + setRedControlPoints(redControlPoints); + setGreenControlPoints(greenControlPoints); + setBlueControlPoints(blueControlPoints); } @Override protected void onDrawArraysPre() { - if (mToneCurveTexture[0] != OpenGlUtils.NO_TEXTURE) { + if (toneCurveTexture[0] != OpenGlUtils.NO_TEXTURE) { GLES20.glActiveTexture(GLES20.GL_TEXTURE3); - GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mToneCurveTexture[0]); - GLES20.glUniform1i(mToneCurveTextureUniformLocation, 3); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, toneCurveTexture[0]); + GLES20.glUniform1i(toneCurveTextureUniformLocation, 3); } } @@ -102,7 +105,7 @@ public void setFromCurveFileInputStream(InputStream input) { int version = readShort(input); int totalCurves = readShort(input); - ArrayList curves = new ArrayList(totalCurves); + ArrayList curves = new ArrayList<>(totalCurves); float pointRate = 1.0f / 255; for (int i = 0; i < totalCurves; i++) { @@ -126,10 +129,10 @@ public void setFromCurveFileInputStream(InputStream input) { } input.close(); - mRgbCompositeControlPoints = curves.get(0); - mRedControlPoints = curves.get(1); - mGreenControlPoints = curves.get(2); - mBlueControlPoints = curves.get(3); + rgbCompositeControlPoints = curves.get(0); + redControlPoints = curves.get(1); + greenControlPoints = curves.get(2); + blueControlPoints = curves.get(3); } catch (IOException e) { e.printStackTrace(); } @@ -140,26 +143,26 @@ private short readShort(InputStream input) throws IOException { } public void setRgbCompositeControlPoints(PointF[] points) { - mRgbCompositeControlPoints = points; - mRgbCompositeCurve = createSplineCurve(mRgbCompositeControlPoints); + rgbCompositeControlPoints = points; + rgbCompositeCurve = createSplineCurve(rgbCompositeControlPoints); updateToneCurveTexture(); } public void setRedControlPoints(PointF[] points) { - mRedControlPoints = points; - mRedCurve = createSplineCurve(mRedControlPoints); + redControlPoints = points; + redCurve = createSplineCurve(redControlPoints); updateToneCurveTexture(); } public void setGreenControlPoints(PointF[] points) { - mGreenControlPoints = points; - mGreenCurve = createSplineCurve(mGreenControlPoints); + greenControlPoints = points; + greenCurve = createSplineCurve(greenControlPoints); updateToneCurveTexture(); } public void setBlueControlPoints(PointF[] points) { - mBlueControlPoints = points; - mBlueCurve = createSplineCurve(mBlueControlPoints); + blueControlPoints = points; + blueCurve = createSplineCurve(blueControlPoints); updateToneCurveTexture(); } @@ -168,16 +171,16 @@ private void updateToneCurveTexture() { @Override public void run() { GLES20.glActiveTexture(GLES20.GL_TEXTURE3); - GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mToneCurveTexture[0]); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, toneCurveTexture[0]); - if ((mRedCurve.size() >= 256) && (mGreenCurve.size() >= 256) && (mBlueCurve.size() >= 256) && (mRgbCompositeCurve.size() >= 256)) { + if ((redCurve.size() >= 256) && (greenCurve.size() >= 256) && (blueCurve.size() >= 256) && (rgbCompositeCurve.size() >= 256)) { byte[] toneCurveByteArray = new byte[256 * 4]; for (int currentCurveIndex = 0; currentCurveIndex < 256; currentCurveIndex++) { // BGRA for upload to texture - toneCurveByteArray[currentCurveIndex * 4 + 2] = (byte) ((int) Math.min(Math.max(currentCurveIndex + mBlueCurve.get(currentCurveIndex) + mRgbCompositeCurve.get(currentCurveIndex), 0), 255) & 0xff); - toneCurveByteArray[currentCurveIndex * 4 + 1] = (byte) ((int) Math.min(Math.max(currentCurveIndex + mGreenCurve.get(currentCurveIndex) + mRgbCompositeCurve.get(currentCurveIndex), 0), 255) & 0xff); - toneCurveByteArray[currentCurveIndex * 4] = (byte) ((int) Math.min(Math.max(currentCurveIndex + mRedCurve.get(currentCurveIndex) + mRgbCompositeCurve.get(currentCurveIndex), 0), 255) & 0xff); - toneCurveByteArray[currentCurveIndex * 4 + 3] = (byte) (255 & 0xff); + toneCurveByteArray[currentCurveIndex * 4 + 2] = (byte) ((int) Math.min(Math.max(currentCurveIndex + blueCurve.get(currentCurveIndex) + rgbCompositeCurve.get(currentCurveIndex), 0), 255) & 0xff); + toneCurveByteArray[currentCurveIndex * 4 + 1] = (byte) ((int) Math.min(Math.max(currentCurveIndex + greenCurve.get(currentCurveIndex) + rgbCompositeCurve.get(currentCurveIndex), 0), 255) & 0xff); + toneCurveByteArray[currentCurveIndex * 4] = (byte) ((int) Math.min(Math.max(currentCurveIndex + redCurve.get(currentCurveIndex) + rgbCompositeCurve.get(currentCurveIndex), 0), 255) & 0xff); + toneCurveByteArray[currentCurveIndex * 4 + 3] = (byte) (0xff); } GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, 256 /*width*/, 1 /*height*/, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, ByteBuffer.wrap(toneCurveByteArray)); @@ -243,7 +246,7 @@ public int compare(PointF point1, PointF point2) { } // Prepare the spline points. - ArrayList preparedSplinePoints = new ArrayList(splinePoints.size()); + ArrayList preparedSplinePoints = new ArrayList<>(splinePoints.size()); for (Point newPoint : splinePoints) { Point origPoint = new Point(newPoint.x, newPoint.x); @@ -276,7 +279,7 @@ private ArrayList createSplineCurve2(Point[] points) { } - ArrayList output = new ArrayList(n + 1); + ArrayList output = new ArrayList<>(n + 1); for (int i = 0; i < n - 1; i++) { Point cur = points[i]; @@ -356,7 +359,7 @@ private ArrayList createSecondDerivative(Point[] points) { result[i] -= k * result[i + 1]; } - ArrayList output = new ArrayList(n); + ArrayList output = new ArrayList<>(n); for (int i = 0; i < n; i++) output.add(result[i] / matrix[i][1]); return output; diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageToonFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageToonFilter.java similarity index 84% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageToonFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageToonFilter.java index 5148d1d01..7a9e274a0 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageToonFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageToonFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; import android.opengl.GLES20; @@ -70,10 +70,10 @@ public class GPUImageToonFilter extends GPUImage3x3TextureSamplingFilter { "gl_FragColor = vec4(posterizedImageColor * thresholdTest, textureColor.a);\n" + "}\n"; - float mThreshold; - int mThresholdLocation; - float mQuantizationLevels; - int mQuantizationLevelsLocation; + private float threshold; + private int thresholdLocation; + private float quantizationLevels; + private int quantizationLevelsLocation; public GPUImageToonFilter() { this(0.2f, 10.0f); @@ -81,22 +81,22 @@ public GPUImageToonFilter() { public GPUImageToonFilter(float threshold, float quantizationLevels) { super(TOON_FRAGMENT_SHADER); - mThreshold = threshold; - mQuantizationLevels = quantizationLevels; + this.threshold = threshold; + this.quantizationLevels = quantizationLevels; } @Override public void onInit() { super.onInit(); - mThresholdLocation = GLES20.glGetUniformLocation(getProgram(), "threshold"); - mQuantizationLevelsLocation = GLES20.glGetUniformLocation(getProgram(), "quantizationLevels"); + thresholdLocation = GLES20.glGetUniformLocation(getProgram(), "threshold"); + quantizationLevelsLocation = GLES20.glGetUniformLocation(getProgram(), "quantizationLevels"); } @Override public void onInitialized() { super.onInitialized(); - setThreshold(mThreshold); - setQuantizationLevels(mQuantizationLevels); + setThreshold(threshold); + setQuantizationLevels(quantizationLevels); } /** @@ -105,8 +105,8 @@ public void onInitialized() { * @param threshold default 0.2 */ public void setThreshold(final float threshold) { - mThreshold = threshold; - setFloat(mThresholdLocation, threshold); + this.threshold = threshold; + setFloat(thresholdLocation, threshold); } /** @@ -115,7 +115,7 @@ public void setThreshold(final float threshold) { * @param quantizationLevels default 10.0 */ public void setQuantizationLevels(final float quantizationLevels) { - mQuantizationLevels = quantizationLevels; - setFloat(mQuantizationLevelsLocation, quantizationLevels); + this.quantizationLevels = quantizationLevels; + setFloat(quantizationLevelsLocation, quantizationLevels); } } diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageTransformFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageTransformFilter.java similarity index 87% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageTransformFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageTransformFilter.java index 0a962cc50..96317da08 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageTransformFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageTransformFilter.java @@ -1,4 +1,20 @@ -package jp.co.cyberagent.android.gpuimage; +/* + * Copyright (C) 2018 CyberAgent, Inc. + * + * 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 jp.co.cyberagent.android.gpuimage.filter; import android.opengl.GLES20; import android.opengl.Matrix; @@ -50,14 +66,13 @@ public void onInit() { super.onInit(); transformMatrixUniform = GLES20.glGetUniformLocation(getProgram(), "transformMatrix"); orthographicMatrixUniform = GLES20.glGetUniformLocation(getProgram(), "orthographicMatrix"); - - setUniformMatrix4f(transformMatrixUniform, transform3D); - setUniformMatrix4f(orthographicMatrixUniform, orthographicMatrix); } @Override public void onInitialized() { super.onInitialized(); + setUniformMatrix4f(transformMatrixUniform, transform3D); + setUniformMatrix4f(orthographicMatrixUniform, orthographicMatrix); } @Override diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageTwoInputFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageTwoInputFilter.java similarity index 61% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageTwoInputFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageTwoInputFilter.java index afc3b8640..64c8d5dba 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageTwoInputFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageTwoInputFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,15 +14,18 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; + +import android.graphics.Bitmap; +import android.opengl.GLES20; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; +import jp.co.cyberagent.android.gpuimage.util.OpenGlUtils; +import jp.co.cyberagent.android.gpuimage.util.Rotation; import jp.co.cyberagent.android.gpuimage.util.TextureRotationUtil; -import android.graphics.Bitmap; -import android.opengl.GLES20; public class GPUImageTwoInputFilter extends GPUImageFilter { private static final String VERTEX_SHADER = "attribute vec4 position;\n" + @@ -39,11 +42,11 @@ public class GPUImageTwoInputFilter extends GPUImageFilter { " textureCoordinate2 = inputTextureCoordinate2.xy;\n" + "}"; - public int mFilterSecondTextureCoordinateAttribute; - public int mFilterInputTextureUniform2; - public int mFilterSourceTexture2 = OpenGlUtils.NO_TEXTURE; - private ByteBuffer mTexture2CoordinatesBuffer; - private Bitmap mBitmap; + private int filterSecondTextureCoordinateAttribute; + private int filterInputTextureUniform2; + private int filterSourceTexture2 = OpenGlUtils.NO_TEXTURE; + private ByteBuffer texture2CoordinatesBuffer; + private Bitmap bitmap; public GPUImageTwoInputFilter(String fragmentShader) { this(VERTEX_SHADER, fragmentShader); @@ -58,64 +61,68 @@ public GPUImageTwoInputFilter(String vertexShader, String fragmentShader) { public void onInit() { super.onInit(); - mFilterSecondTextureCoordinateAttribute = GLES20.glGetAttribLocation(getProgram(), "inputTextureCoordinate2"); - mFilterInputTextureUniform2 = GLES20.glGetUniformLocation(getProgram(), "inputImageTexture2"); // This does assume a name of "inputImageTexture2" for second input texture in the fragment shader - GLES20.glEnableVertexAttribArray(mFilterSecondTextureCoordinateAttribute); + filterSecondTextureCoordinateAttribute = GLES20.glGetAttribLocation(getProgram(), "inputTextureCoordinate2"); + filterInputTextureUniform2 = GLES20.glGetUniformLocation(getProgram(), "inputImageTexture2"); // This does assume a name of "inputImageTexture2" for second input texture in the fragment shader + GLES20.glEnableVertexAttribArray(filterSecondTextureCoordinateAttribute); + } - if (mBitmap != null&&!mBitmap.isRecycled()) { - setBitmap(mBitmap); + @Override + public void onInitialized() { + super.onInitialized(); + if (bitmap != null && !bitmap.isRecycled()) { + setBitmap(bitmap); } } - + public void setBitmap(final Bitmap bitmap) { if (bitmap != null && bitmap.isRecycled()) { return; } - mBitmap = bitmap; - if (mBitmap == null) { + this.bitmap = bitmap; + if (this.bitmap == null) { return; } runOnDraw(new Runnable() { public void run() { - if (mFilterSourceTexture2 == OpenGlUtils.NO_TEXTURE) { + if (filterSourceTexture2 == OpenGlUtils.NO_TEXTURE) { if (bitmap == null || bitmap.isRecycled()) { return; } GLES20.glActiveTexture(GLES20.GL_TEXTURE3); - mFilterSourceTexture2 = OpenGlUtils.loadTexture(bitmap, OpenGlUtils.NO_TEXTURE, false); + filterSourceTexture2 = OpenGlUtils.loadTexture(bitmap, OpenGlUtils.NO_TEXTURE, false); } } }); } public Bitmap getBitmap() { - return mBitmap; + return bitmap; } public void recycleBitmap() { - if (mBitmap != null && !mBitmap.isRecycled()) { - mBitmap.recycle(); - mBitmap = null; + if (bitmap != null && !bitmap.isRecycled()) { + bitmap.recycle(); + bitmap = null; } } public void onDestroy() { super.onDestroy(); GLES20.glDeleteTextures(1, new int[]{ - mFilterSourceTexture2 + filterSourceTexture2 }, 0); - mFilterSourceTexture2 = OpenGlUtils.NO_TEXTURE; + filterSourceTexture2 = OpenGlUtils.NO_TEXTURE; } @Override protected void onDrawArraysPre() { - GLES20.glEnableVertexAttribArray(mFilterSecondTextureCoordinateAttribute); + GLES20.glEnableVertexAttribArray(filterSecondTextureCoordinateAttribute); GLES20.glActiveTexture(GLES20.GL_TEXTURE3); - GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mFilterSourceTexture2); - GLES20.glUniform1i(mFilterInputTextureUniform2, 3); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, filterSourceTexture2); + GLES20.glUniform1i(filterInputTextureUniform2, 3); - mTexture2CoordinatesBuffer.position(0); - GLES20.glVertexAttribPointer(mFilterSecondTextureCoordinateAttribute, 2, GLES20.GL_FLOAT, false, 0, mTexture2CoordinatesBuffer); + texture2CoordinatesBuffer.position(0); + GLES20.glVertexAttribPointer(filterSecondTextureCoordinateAttribute, 2, GLES20.GL_FLOAT, false, 0, texture2CoordinatesBuffer); } public void setRotation(final Rotation rotation, final boolean flipHorizontal, final boolean flipVertical) { @@ -126,6 +133,6 @@ public void setRotation(final Rotation rotation, final boolean flipHorizontal, f fBuffer.put(buffer); fBuffer.flip(); - mTexture2CoordinatesBuffer = bBuffer; + texture2CoordinatesBuffer = bBuffer; } } diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageTwoPassFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageTwoPassFilter.java similarity index 91% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageTwoPassFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageTwoPassFilter.java index bf3fbf172..8e4925704 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageTwoPassFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageTwoPassFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; public class GPUImageTwoPassFilter extends GPUImageFilterGroup { public GPUImageTwoPassFilter(String firstVertexShader, String firstFragmentShader, diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageTwoPassTextureSamplingFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageTwoPassTextureSamplingFilter.java similarity index 86% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageTwoPassTextureSamplingFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageTwoPassTextureSamplingFilter.java index 19c0365b2..219a7b1aa 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageTwoPassTextureSamplingFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageTwoPassTextureSamplingFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; import android.opengl.GLES20; @@ -33,18 +33,18 @@ public void onInit() { protected void initTexelOffsets() { float ratio = getHorizontalTexelOffsetRatio(); - GPUImageFilter filter = mFilters.get(0); + GPUImageFilter filter = getFilters().get(0); int texelWidthOffsetLocation = GLES20.glGetUniformLocation(filter.getProgram(), "texelWidthOffset"); int texelHeightOffsetLocation = GLES20.glGetUniformLocation(filter.getProgram(), "texelHeightOffset"); - filter.setFloat(texelWidthOffsetLocation, ratio / mOutputWidth); + filter.setFloat(texelWidthOffsetLocation, ratio / getOutputWidth()); filter.setFloat(texelHeightOffsetLocation, 0); ratio = getVerticalTexelOffsetRatio(); - filter = mFilters.get(1); + filter = getFilters().get(1); texelWidthOffsetLocation = GLES20.glGetUniformLocation(filter.getProgram(), "texelWidthOffset"); texelHeightOffsetLocation = GLES20.glGetUniformLocation(filter.getProgram(), "texelHeightOffset"); filter.setFloat(texelWidthOffsetLocation, 0); - filter.setFloat(texelHeightOffsetLocation, ratio / mOutputHeight); + filter.setFloat(texelHeightOffsetLocation, ratio / getOutputHeight()); } @Override diff --git a/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageVibranceFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageVibranceFilter.java new file mode 100644 index 000000000..13291234a --- /dev/null +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageVibranceFilter.java @@ -0,0 +1,52 @@ +package jp.co.cyberagent.android.gpuimage.filter; + +import android.opengl.GLES20; + +public class GPUImageVibranceFilter extends GPUImageFilter { + public static final String VIBRANCE_FRAGMENT_SHADER = "" + + "varying highp vec2 textureCoordinate;\n" + + "\n" + + "uniform sampler2D inputImageTexture;\n" + + "uniform lowp float vibrance;\n" + + "\n" + + "void main() {\n" + + " lowp vec4 color = texture2D(inputImageTexture, textureCoordinate);\n" + + " lowp float average = (color.r + color.g + color.b) / 3.0;\n" + + " lowp float mx = max(color.r, max(color.g, color.b));\n" + + " lowp float amt = (mx - average) * (-vibrance * 3.0);\n" + + " color.rgb = mix(color.rgb, vec3(mx), amt);\n" + + " gl_FragColor = color;\n" + + "}"; + + private int vibranceLocation; + private float vibrance; + + @Override + public void onInit() { + super.onInit(); + vibranceLocation = GLES20.glGetUniformLocation(getProgram(), "vibrance"); + } + + public GPUImageVibranceFilter() { + this(0f); + } + + public GPUImageVibranceFilter(float vibrance) { + super(NO_FILTER_VERTEX_SHADER, VIBRANCE_FRAGMENT_SHADER); + this.vibrance = vibrance; + } + + @Override + public void onInitialized() { + super.onInitialized(); + setVibrance(vibrance); + } + + public void setVibrance(final float vibrance) { + this.vibrance = vibrance; + if (isInitialized()) { + setFloat(vibranceLocation, vibrance); + } + } +} + diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageVignetteFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageVignetteFilter.java similarity index 62% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageVignetteFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageVignetteFilter.java index 439e8bd0d..81b44b111 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageVignetteFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageVignetteFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; import android.graphics.PointF; import android.opengl.GLES20; @@ -49,60 +49,63 @@ public class GPUImageVignetteFilter extends GPUImageFilter { " gl_FragColor = vec4(mix(rgb.x, vignetteColor.x, percent), mix(rgb.y, vignetteColor.y, percent), mix(rgb.z, vignetteColor.z, percent), 1.0);\n" + " }"; - private int mVignetteCenterLocation; - private PointF mVignetteCenter; - private int mVignetteColorLocation; - private float[] mVignetteColor; - private int mVignetteStartLocation; - private float mVignetteStart; - private int mVignetteEndLocation; - private float mVignetteEnd; - + private int vignetteCenterLocation; + private PointF vignetteCenter; + private int vignetteColorLocation; + private float[] vignetteColor; + private int vignetteStartLocation; + private float vignetteStart; + private int vignetteEndLocation; + private float vignetteEnd; + public GPUImageVignetteFilter() { - this(new PointF(), new float[] {0.0f, 0.0f, 0.0f}, 0.3f, 0.75f); + this(new PointF(), new float[]{0.0f, 0.0f, 0.0f}, 0.3f, 0.75f); } - + public GPUImageVignetteFilter(final PointF vignetteCenter, final float[] vignetteColor, final float vignetteStart, final float vignetteEnd) { super(NO_FILTER_VERTEX_SHADER, VIGNETTING_FRAGMENT_SHADER); - mVignetteCenter = vignetteCenter; - mVignetteColor = vignetteColor; - mVignetteStart = vignetteStart; - mVignetteEnd = vignetteEnd; - + this.vignetteCenter = vignetteCenter; + this.vignetteColor = vignetteColor; + this.vignetteStart = vignetteStart; + this.vignetteEnd = vignetteEnd; + } @Override public void onInit() { super.onInit(); - mVignetteCenterLocation = GLES20.glGetUniformLocation(getProgram(), "vignetteCenter"); - mVignetteColorLocation = GLES20.glGetUniformLocation(getProgram(), "vignetteColor"); - mVignetteStartLocation = GLES20.glGetUniformLocation(getProgram(), "vignetteStart"); - mVignetteEndLocation = GLES20.glGetUniformLocation(getProgram(), "vignetteEnd"); - - setVignetteCenter(mVignetteCenter); - setVignetteColor(mVignetteColor); - setVignetteStart(mVignetteStart); - setVignetteEnd(mVignetteEnd); + vignetteCenterLocation = GLES20.glGetUniformLocation(getProgram(), "vignetteCenter"); + vignetteColorLocation = GLES20.glGetUniformLocation(getProgram(), "vignetteColor"); + vignetteStartLocation = GLES20.glGetUniformLocation(getProgram(), "vignetteStart"); + vignetteEndLocation = GLES20.glGetUniformLocation(getProgram(), "vignetteEnd"); } + @Override + public void onInitialized() { + super.onInitialized(); + setVignetteCenter(vignetteCenter); + setVignetteColor(vignetteColor); + setVignetteStart(vignetteStart); + setVignetteEnd(vignetteEnd); + } public void setVignetteCenter(final PointF vignetteCenter) { - mVignetteCenter = vignetteCenter; - setPoint(mVignetteCenterLocation, mVignetteCenter); + this.vignetteCenter = vignetteCenter; + setPoint(vignetteCenterLocation, this.vignetteCenter); } public void setVignetteColor(final float[] vignetteColor) { - mVignetteColor = vignetteColor; - setFloatVec3(mVignetteColorLocation, mVignetteColor); + this.vignetteColor = vignetteColor; + setFloatVec3(vignetteColorLocation, this.vignetteColor); } - + public void setVignetteStart(final float vignetteStart) { - mVignetteStart = vignetteStart; - setFloat(mVignetteStartLocation, mVignetteStart); + this.vignetteStart = vignetteStart; + setFloat(vignetteStartLocation, this.vignetteStart); } - + public void setVignetteEnd(final float vignetteEnd) { - mVignetteEnd = vignetteEnd; - setFloat(mVignetteEndLocation, mVignetteEnd); + this.vignetteEnd = vignetteEnd; + setFloat(vignetteEndLocation, this.vignetteEnd); } } diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageWeakPixelInclusionFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageWeakPixelInclusionFilter.java similarity index 97% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageWeakPixelInclusionFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageWeakPixelInclusionFilter.java index 3e1b8f01c..3dbcc9999 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageWeakPixelInclusionFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageWeakPixelInclusionFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; public class GPUImageWeakPixelInclusionFilter extends GPUImage3x3TextureSamplingFilter { public static final String WEAKPIXEL_FRAGMENT_SHADER = "" + diff --git a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageWhiteBalanceFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageWhiteBalanceFilter.java similarity index 75% rename from library/src/jp/co/cyberagent/android/gpuimage/GPUImageWhiteBalanceFilter.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageWhiteBalanceFilter.java index 1818da992..8bb202525 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/GPUImageWhiteBalanceFilter.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageWhiteBalanceFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,14 +14,14 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.filter; import android.opengl.GLES20; /** * Adjusts the white balance of incoming image.
*
- * temperature: + * temperature: * tint: */ public class GPUImageWhiteBalanceFilter extends GPUImageFilter { @@ -53,39 +53,42 @@ public class GPUImageWhiteBalanceFilter extends GPUImageFilter { " gl_FragColor = vec4(mix(rgb, processed, temperature), source.a);\n" + "}"; - private int mTemperatureLocation; - private float mTemperature; - private int mTintLocation; - private float mTint; + private int temperatureLocation; + private float temperature; + private int tintLocation; + private float tint; public GPUImageWhiteBalanceFilter() { this(5000.0f, 0.0f); } - + public GPUImageWhiteBalanceFilter(final float temperature, final float tint) { super(NO_FILTER_VERTEX_SHADER, WHITE_BALANCE_FRAGMENT_SHADER); - mTemperature = temperature; - mTint = tint; + this.temperature = temperature; + this.tint = tint; } @Override public void onInit() { super.onInit(); - mTemperatureLocation = GLES20.glGetUniformLocation(getProgram(), "temperature"); - mTintLocation = GLES20.glGetUniformLocation(getProgram(), "tint"); - - setTemperature(mTemperature); - setTint(mTint); + temperatureLocation = GLES20.glGetUniformLocation(getProgram(), "temperature"); + tintLocation = GLES20.glGetUniformLocation(getProgram(), "tint"); } + @Override + public void onInitialized() { + super.onInitialized(); + setTemperature(temperature); + setTint(tint); + } public void setTemperature(final float temperature) { - mTemperature = temperature; - setFloat(mTemperatureLocation, mTemperature < 5000 ? (float)(0.0004 * (mTemperature-5000.0)) : (float)(0.00006 * (mTemperature-5000.0))); + this.temperature = temperature; + setFloat(temperatureLocation, this.temperature < 5000 ? (float) (0.0004 * (this.temperature - 5000.0)) : (float) (0.00006 * (this.temperature - 5000.0))); } - + public void setTint(final float tint) { - mTint = tint; - setFloat(mTintLocation, (float)(mTint/100.0)); + this.tint = tint; + setFloat(tintLocation, (float) (this.tint / 100.0)); } } diff --git a/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageZoomBlurFilter.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageZoomBlurFilter.java new file mode 100644 index 000000000..14f5a9556 --- /dev/null +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/filter/GPUImageZoomBlurFilter.java @@ -0,0 +1,71 @@ +package jp.co.cyberagent.android.gpuimage.filter; + +import android.graphics.PointF; +import android.opengl.GLES20; + +public class GPUImageZoomBlurFilter extends GPUImageFilter { + public static final String ZOOM_BLUR_FRAGMENT_SHADER = "" + + "varying highp vec2 textureCoordinate;\n" + + "\n" + + "uniform sampler2D inputImageTexture;\n" + + "\n" + + "uniform highp vec2 blurCenter;\n" + + "uniform highp float blurSize;\n" + + "\n" + + "void main()\n" + + "{\n" + + " // TODO: Do a more intelligent scaling based on resolution here\n" + + " highp vec2 samplingOffset = 1.0/100.0 * (blurCenter - textureCoordinate) * blurSize;\n" + + " \n" + + " lowp vec4 fragmentColor = texture2D(inputImageTexture, textureCoordinate) * 0.18;\n" + + " fragmentColor += texture2D(inputImageTexture, textureCoordinate + samplingOffset) * 0.15;\n" + + " fragmentColor += texture2D(inputImageTexture, textureCoordinate + (2.0 * samplingOffset)) * 0.12;\n" + + " fragmentColor += texture2D(inputImageTexture, textureCoordinate + (3.0 * samplingOffset)) * 0.09;\n" + + " fragmentColor += texture2D(inputImageTexture, textureCoordinate + (4.0 * samplingOffset)) * 0.05;\n" + + " fragmentColor += texture2D(inputImageTexture, textureCoordinate - samplingOffset) * 0.15;\n" + + " fragmentColor += texture2D(inputImageTexture, textureCoordinate - (2.0 * samplingOffset)) * 0.12;\n" + + " fragmentColor += texture2D(inputImageTexture, textureCoordinate - (3.0 * samplingOffset)) * 0.09;\n" + + " fragmentColor += texture2D(inputImageTexture, textureCoordinate - (4.0 * samplingOffset)) * 0.05;\n" + + " \n" + + " gl_FragColor = fragmentColor;\n" + + "}\n"; + + private PointF blurCenter; + private int blurCenterLocation; + private float blurSize; + private int blurSizeLocation; + + public GPUImageZoomBlurFilter() { + this(new PointF(0.5f, 0.5f), 1.0f); + } + + public GPUImageZoomBlurFilter(PointF blurCenter, float blurSize) { + super(NO_FILTER_VERTEX_SHADER, ZOOM_BLUR_FRAGMENT_SHADER); + this.blurCenter = blurCenter; + this.blurSize = blurSize; + } + + @Override + public void onInit() { + super.onInit(); + blurCenterLocation = GLES20.glGetUniformLocation(getProgram(), "blurCenter"); + blurSizeLocation = GLES20.glGetUniformLocation(getProgram(), "blurSize"); + } + + @Override + public void onInitialized() { + super.onInitialized(); + setBlurCenter(blurCenter); + setBlurSize(blurSize); + } + + public void setBlurCenter(final PointF blurCenter) { + this.blurCenter = blurCenter; + setPoint(blurCenterLocation, blurCenter); + } + + public void setBlurSize(final float blurSize) { + this.blurSize = blurSize; + setFloat(blurSizeLocation, blurSize); + } +} diff --git a/library/src/jp/co/cyberagent/android/gpuimage/OpenGlUtils.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/util/OpenGlUtils.java similarity index 94% rename from library/src/jp/co/cyberagent/android/gpuimage/OpenGlUtils.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/util/OpenGlUtils.java index e85897041..efb810a8b 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/OpenGlUtils.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/util/OpenGlUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,9 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; - -import java.nio.IntBuffer; +package jp.co.cyberagent.android.gpuimage.util; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; @@ -25,6 +23,8 @@ import android.opengl.GLUtils; import android.util.Log; +import java.nio.IntBuffer; + public class OpenGlUtils { public static final int NO_TEXTURE = -1; @@ -58,7 +58,7 @@ public static int loadTexture(final Bitmap img, final int usedTexId, final boole return textures[0]; } - public static int loadTexture(final IntBuffer data, final Size size, final int usedTexId) { + public static int loadTexture(final IntBuffer data, final int width, final int height, final int usedTexId) { int textures[] = new int[1]; if (usedTexId == NO_TEXTURE) { GLES20.glGenTextures(1, textures, 0); @@ -71,12 +71,12 @@ public static int loadTexture(final IntBuffer data, final Size size, final int u GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); - GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, size.width, size.height, + GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, data); } else { GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, usedTexId); - GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, size.width, - size.height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, data); + GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, width, + height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, data); textures[0] = usedTexId; } return textures[0]; diff --git a/library/src/jp/co/cyberagent/android/gpuimage/Rotation.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/util/Rotation.java similarity index 56% rename from library/src/jp/co/cyberagent/android/gpuimage/Rotation.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/util/Rotation.java index bd2e840ef..bfc6d900e 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/Rotation.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/util/Rotation.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package jp.co.cyberagent.android.gpuimage; +package jp.co.cyberagent.android.gpuimage.util; public enum Rotation { NORMAL, ROTATION_90, ROTATION_180, ROTATION_270; @@ -26,11 +26,16 @@ public enum Rotation { */ public int asInt() { switch (this) { - case NORMAL: return 0; - case ROTATION_90: return 90; - case ROTATION_180: return 180; - case ROTATION_270: return 270; - default: throw new IllegalStateException("Unknown Rotation!"); + case NORMAL: + return 0; + case ROTATION_90: + return 90; + case ROTATION_180: + return 180; + case ROTATION_270: + return 270; + default: + throw new IllegalStateException("Unknown Rotation!"); } } @@ -42,13 +47,19 @@ public int asInt() { */ public static Rotation fromInt(int rotation) { switch (rotation) { - case 0: return NORMAL; - case 90: return ROTATION_90; - case 180: return ROTATION_180; - case 270: return ROTATION_270; - case 360: return NORMAL; - default: throw new IllegalStateException( - rotation + " is an unknown rotation. Needs to be either 0, 90, 180 or 270!"); + case 0: + return NORMAL; + case 90: + return ROTATION_90; + case 180: + return ROTATION_180; + case 270: + return ROTATION_270; + case 360: + return NORMAL; + default: + throw new IllegalStateException( + rotation + " is an unknown rotation. Needs to be either 0, 90, 180 or 270!"); } } } diff --git a/library/src/jp/co/cyberagent/android/gpuimage/util/TextureRotationUtil.java b/library/src/main/java/jp/co/cyberagent/android/gpuimage/util/TextureRotationUtil.java similarity index 94% rename from library/src/jp/co/cyberagent/android/gpuimage/util/TextureRotationUtil.java rename to library/src/main/java/jp/co/cyberagent/android/gpuimage/util/TextureRotationUtil.java index c439d914f..53c42e750 100644 --- a/library/src/jp/co/cyberagent/android/gpuimage/util/TextureRotationUtil.java +++ b/library/src/main/java/jp/co/cyberagent/android/gpuimage/util/TextureRotationUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 CyberAgent + * Copyright (C) 2018 CyberAgent, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,8 +16,6 @@ package jp.co.cyberagent.android.gpuimage.util; -import jp.co.cyberagent.android.gpuimage.Rotation; - public class TextureRotationUtil { public static final float TEXTURE_NO_ROTATION[] = { @@ -50,7 +48,7 @@ private TextureRotationUtil() { } public static float[] getRotation(final Rotation rotation, final boolean flipHorizontal, - final boolean flipVertical) { + final boolean flipVertical) { float[] rotatedTex; switch (rotation) { case ROTATION_90: diff --git a/library/src/main/res/values/attrs.xml b/library/src/main/res/values/attrs.xml new file mode 100644 index 000000000..f8cf91d11 --- /dev/null +++ b/library/src/main/res/values/attrs.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/sample/build.gradle b/sample/build.gradle index f64f4a42b..ed3d3249c 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -1,39 +1,37 @@ apply plugin: 'com.android.application' +apply plugin: 'kotlin-android-extensions' +apply plugin: 'kotlin-android' android { compileSdkVersion COMPILE_SDK_VERSION as int - buildToolsVersion BUILD_TOOLS_VERSION defaultConfig { minSdkVersion MIN_SDK_VERSION as int targetSdkVersion TARGET_SDK_VERSION as int - } - - sourceSets { - main { - manifest.srcFile 'AndroidManifest.xml' - java.srcDirs = ['src'] - resources.srcDirs = ['src'] - aidl.srcDirs = ['src'] - renderscript.srcDirs = ['src'] - res.srcDirs = ['res'] - assets.srcDirs = ['assets'] - } - instrumentTest.setRoot('tests') + versionCode = VERSION_CODE as int + versionName = VERSION_NAME } - lintOptions { - abortOnError true + buildTypes { + debug { + debuggable true + } + release { + debuggable false + zipAlignEnabled true + minifyEnabled true + shrinkResources true + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } } } repositories { - jcenter() - maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } +// maven { url = "https://oss.sonatype.org/content/repositories/snapshots"} } dependencies { - compile project(':library') -// compile 'jp.co.cyberagent.android.gpuimage:gpuimage-library:1.4.1' - compile 'com.android.support:support-v4:23.1.1' + implementation project(':library') + implementation 'androidx.appcompat:appcompat:1.2.0' + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" } \ No newline at end of file diff --git a/sample/ic_launcher-web.png b/sample/ic_launcher-web.png deleted file mode 100644 index 817b96c1d..000000000 Binary files a/sample/ic_launcher-web.png and /dev/null differ diff --git a/sample/project.properties b/sample/project.properties deleted file mode 100644 index 24e0cbf3b..000000000 --- a/sample/project.properties +++ /dev/null @@ -1,16 +0,0 @@ -# This file is automatically generated by Android Tools. -# Do not modify this file -- YOUR CHANGES WILL BE ERASED! -# -# This file must be checked in Version Control Systems. -# -# To customize properties used by the Ant build system edit -# "ant.properties", and override values to adapt the script to your -# project structure. -# -# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): -#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt - -# Project target. -target=android-16 -proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt -android.library.reference.1=../library \ No newline at end of file diff --git a/sample/res/drawable-hdpi/ic_launcher.png b/sample/res/drawable-hdpi/ic_launcher.png deleted file mode 100644 index 301100c35..000000000 Binary files a/sample/res/drawable-hdpi/ic_launcher.png and /dev/null differ diff --git a/sample/res/drawable-ldpi/ic_launcher.png b/sample/res/drawable-ldpi/ic_launcher.png deleted file mode 100644 index 6e1bfd534..000000000 Binary files a/sample/res/drawable-ldpi/ic_launcher.png and /dev/null differ diff --git a/sample/res/drawable-mdpi/ic_launcher.png b/sample/res/drawable-mdpi/ic_launcher.png deleted file mode 100644 index 372e87fb8..000000000 Binary files a/sample/res/drawable-mdpi/ic_launcher.png and /dev/null differ diff --git a/sample/res/drawable-xhdpi/ic_launcher.png b/sample/res/drawable-xhdpi/ic_launcher.png deleted file mode 100644 index d9de8e016..000000000 Binary files a/sample/res/drawable-xhdpi/ic_launcher.png and /dev/null differ diff --git a/sample/res/values-v11/styles.xml b/sample/res/values-v11/styles.xml deleted file mode 100644 index d408cbc37..000000000 --- a/sample/res/values-v11/styles.xml +++ /dev/null @@ -1,5 +0,0 @@ - - -