├── .gitignore
├── .idea
├── codeStyles
│ └── Project.xml
├── gradle.xml
├── misc.xml
└── runConfigurations.xml
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── dming
│ │ └── testopengl
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── assets
│ │ └── animation.mp4
│ ├── java
│ │ └── com
│ │ │ └── dming
│ │ │ └── testopengl
│ │ │ ├── CameraActivity.java
│ │ │ ├── CameraRenderer.java
│ │ │ ├── CameraSize.java
│ │ │ ├── LauncherActivity.java
│ │ │ ├── filter
│ │ │ ├── BaseFilter.java
│ │ │ ├── BlurFilter.java
│ │ │ ├── BurrFilter.java
│ │ │ ├── CutApartFilter.java
│ │ │ ├── EdgeFilter.java
│ │ │ ├── IShader.java
│ │ │ ├── LuminanceFilter.java
│ │ │ ├── MultipleFilter.java
│ │ │ ├── ShowGifFilter.java
│ │ │ ├── ShowMovieFilter.java
│ │ │ └── SoulFilter.java
│ │ │ └── utils
│ │ │ ├── DLog.java
│ │ │ ├── FGLUtils.java
│ │ │ ├── GLInterpolator.java
│ │ │ └── ShaderHelper.java
│ └── res
│ │ ├── drawable-xxhdpi
│ │ ├── t_gl.jpg
│ │ └── test_gl.jpg
│ │ ├── layout
│ │ ├── act_test.xml
│ │ └── activity_main.xml
│ │ ├── mipmap-xxhdpi
│ │ └── ic_launcher.png
│ │ ├── raw
│ │ ├── animation_frg.glsl
│ │ ├── blur_frg.glsl
│ │ ├── burr_frg.glsl
│ │ ├── edge_frg.glsl
│ │ ├── luminance_frg.glsl
│ │ ├── multiple_frg.glsl
│ │ ├── n_blur_frg.glsl
│ │ ├── process_frg.glsl
│ │ ├── process_ver.glsl
│ │ ├── sharpen_frg.glsl
│ │ └── soul_frg.glsl
│ │ └── values
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── dming
│ └── testopengl
│ └── ExampleUnitTest.java
├── build.gradle
├── giflib
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── dming
│ │ └── giflib
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── assets
│ │ ├── mogutou.gif
│ │ └── mogutou2.gif
│ ├── cpp
│ │ ├── CMakeLists.txt
│ │ ├── GLUtils.cpp
│ │ ├── GLUtils.h
│ │ ├── GifJni.cpp
│ │ ├── GifPlayer.cpp
│ │ ├── GifPlayer.h
│ │ ├── PthreadSleep.cpp
│ │ ├── PthreadSleep.h
│ │ ├── SyncTime.cpp
│ │ ├── SyncTime.h
│ │ ├── giflib
│ │ │ ├── config.h
│ │ │ ├── dgif_lib.c
│ │ │ ├── egif_lib.c
│ │ │ ├── gif_err.c
│ │ │ ├── gif_font.c
│ │ │ ├── gif_hash.c
│ │ │ ├── gif_hash.h
│ │ │ ├── gif_lib.h
│ │ │ ├── gif_lib_private.h
│ │ │ ├── gifalloc.c
│ │ │ ├── openbsd-reallocarray.c
│ │ │ └── quantize.c
│ │ └── log.h
│ ├── java
│ │ └── com
│ │ │ └── dming
│ │ │ └── testgif
│ │ │ ├── DLog.java
│ │ │ ├── EglHelper.java
│ │ │ ├── FGLUtils.java
│ │ │ ├── GifFilter.java
│ │ │ ├── GifPlayer.java
│ │ │ └── ShaderHelper.java
│ └── res
│ │ └── raw
│ │ ├── gif_process_frg.glsl
│ │ └── gif_process_ver.glsl
│ └── test
│ └── java
│ └── com
│ └── dming
│ └── giflib
│ └── ExampleUnitTest.java
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── mdSrc
├── demo.gif
└── nine_gl.apk
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/libraries
5 | /.idea/modules.xml
6 | /.idea/workspace.xml
7 | .DS_Store
8 | /build
9 | /captures
10 | .externalNativeBuild
11 | .idea/encodings.xml
12 | .idea/vcs.xml
13 | giflib/.cxx/
14 |
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | xmlns:android
14 |
15 | ^$
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | xmlns:.*
25 |
26 | ^$
27 |
28 |
29 | BY_NAME
30 |
31 |
32 |
33 |
34 |
35 |
36 | .*:id
37 |
38 | http://schemas.android.com/apk/res/android
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | .*:name
48 |
49 | http://schemas.android.com/apk/res/android
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 | name
59 |
60 | ^$
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 | style
70 |
71 | ^$
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | .*
81 |
82 | ^$
83 |
84 |
85 | BY_NAME
86 |
87 |
88 |
89 |
90 |
91 |
92 | .*
93 |
94 | http://schemas.android.com/apk/res/android
95 |
96 |
97 | ANDROID_ATTRIBUTE_ORDER
98 |
99 |
100 |
101 |
102 |
103 |
104 | .*
105 |
106 | .*
107 |
108 |
109 | BY_NAME
110 |
111 |
112 |
113 |
114 |
115 |
116 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
20 |
21 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 28
5 | defaultConfig {
6 | applicationId "com.dming.testopengl"
7 | minSdkVersion 17
8 | targetSdkVersion 28
9 | versionCode 1
10 | versionName "1.0"
11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | // compileOptions {
20 | // targetCompatibility JavaVersion.VERSION_1_8
21 | // }
22 | }
23 |
24 | dependencies {
25 | implementation fileTree(dir: 'libs', include: ['*.jar'])
26 | implementation 'com.android.support:appcompat-v7:28.0.0'
27 | implementation 'com.android.support.constraint:constraint-layout:1.1.3'
28 | testImplementation 'junit:junit:4.12'
29 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
30 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
31 | implementation project(path: ':giflib')
32 | }
33 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/dming/testopengl/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.dming.testopengl;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.dming.testopengl", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/assets/animation.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DMings/LearnOpengl/4f3c4d0974c29d8da6672a3acf4187e828f80a92/app/src/main/assets/animation.mp4
--------------------------------------------------------------------------------
/app/src/main/java/com/dming/testopengl/CameraActivity.java:
--------------------------------------------------------------------------------
1 | package com.dming.testopengl;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.app.Activity;
5 | import android.content.Context;
6 | import android.graphics.Point;
7 | import android.graphics.SurfaceTexture;
8 | import android.hardware.Camera;
9 | import android.opengl.GLSurfaceView;
10 | import android.os.Bundle;
11 | import android.support.annotation.Nullable;
12 | import android.support.v7.app.AppCompatActivity;
13 | import android.view.GestureDetector;
14 | import android.view.MotionEvent;
15 | import android.view.Surface;
16 | import android.view.View;
17 | import android.view.WindowManager;
18 |
19 | import com.dming.testopengl.utils.DLog;
20 |
21 | import java.io.IOException;
22 | import java.util.ArrayList;
23 | import java.util.List;
24 | import java.util.SortedSet;
25 | import java.util.TreeSet;
26 |
27 | public class CameraActivity extends AppCompatActivity implements CameraRenderer.GLRunnable {
28 |
29 | private GLSurfaceView mGLSurfaceView;
30 | private CameraRenderer mCameraRenderer;
31 | //
32 | private int mCameraId;
33 | private Camera mCamera;
34 | private Camera.Parameters mCameraParameters;
35 | private final Camera.CameraInfo mCameraInfo = new Camera.CameraInfo();
36 | private static final int INVALID_CAMERA_ID = -1;
37 | protected final List mPreviewSizes = new ArrayList<>();
38 | private SurfaceTexture mSurfaceTexture;
39 | private float[] mCameraMatrix = new float[16];
40 |
41 | @SuppressLint("ClickableViewAccessibility")
42 | @Override
43 | protected void onCreate(@Nullable Bundle savedInstanceState) {
44 | super.onCreate(savedInstanceState);
45 | setContentView(R.layout.activity_main);
46 | mGLSurfaceView = findViewById(R.id.gl_show);
47 | mGLSurfaceView.setEGLContextClientVersion(2);
48 | mCameraRenderer = new CameraRenderer(mGLSurfaceView, this);
49 | mGLSurfaceView.setRenderer(mCameraRenderer);
50 | mGLSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
51 | final GestureDetector.SimpleOnGestureListener listener = new GestureDetector.SimpleOnGestureListener() {
52 |
53 | @Override
54 | public boolean onSingleTapUp(MotionEvent e) {
55 | int w = mGLSurfaceView.getWidth();
56 | int h = mGLSurfaceView.getHeight();
57 | int w_3 = w / 3;
58 | int h_3 = h / 3;
59 | int x = (int) ((e.getX() - 5) / w_3);
60 | int y = (int) ((e.getY() - 5) / h_3);
61 | int index = x + y * 3;
62 | mCameraRenderer.chooseOneShaderOfNine(index);
63 | return true;
64 | }
65 | };
66 | final GestureDetector gestureDetector = new GestureDetector(this, listener);
67 | mGLSurfaceView.setOnTouchListener(new View.OnTouchListener() {
68 | @Override
69 | public boolean onTouch(View v, MotionEvent event) {
70 | gestureDetector.onTouchEvent(event);
71 | return true;
72 | }
73 | });
74 | }
75 |
76 | @Override
77 | public void onSurfaceCreated(final int textureId) {
78 | mSurfaceTexture = new SurfaceTexture(textureId);
79 | mSurfaceTexture.setOnFrameAvailableListener(new SurfaceTexture.OnFrameAvailableListener() {
80 | @Override
81 | public void onFrameAvailable(SurfaceTexture surfaceTexture) {
82 | mGLSurfaceView.queueEvent(new Runnable() {
83 | @Override
84 | public void run() {
85 | if (mSurfaceTexture != null) {
86 | mSurfaceTexture.updateTexImage();
87 | mSurfaceTexture.getTransformMatrix(mCameraMatrix);
88 | mCameraRenderer.setTexMatrix(mCameraMatrix);
89 | mGLSurfaceView.requestRender();
90 | }
91 | }
92 | });
93 | }
94 | });
95 | chooseCamera();
96 | openCamera();
97 | if (isCameraOpened()) {
98 | try {
99 | mCamera.setPreviewTexture(mSurfaceTexture);
100 | } catch (IOException e) {
101 | }
102 | setCameraDisplayOrientation(this, mCamera, mCameraInfo);
103 | adjustCameraParameters();
104 | }
105 | }
106 |
107 | @Override
108 | public void onSurfaceChanged(final int width, final int height) {
109 | mCameraRenderer.onSurfaceCreated(width, height);
110 | }
111 |
112 | @Override
113 | protected void onResume() {
114 | super.onResume();
115 | mGLSurfaceView.onResume();
116 | }
117 |
118 | @Override
119 | protected void onPause() {
120 | mGLSurfaceView.queueEvent(new Runnable() {
121 | @Override
122 | public void run() {
123 | if (isCameraOpened()) {
124 | mCamera.stopPreview();
125 | }
126 | releaseCamera();
127 | mCameraRenderer.onDestroy();
128 | if (mSurfaceTexture != null) {
129 | mSurfaceTexture.release();
130 | mSurfaceTexture = null;
131 | }
132 | }
133 | });
134 | mGLSurfaceView.onPause();
135 | super.onPause();
136 | }
137 |
138 | private void chooseCamera() {
139 | for (int i = 0, count = Camera.getNumberOfCameras(); i < count; i++) {
140 | Camera.getCameraInfo(i, mCameraInfo);
141 | if (mCameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
142 | mCameraId = i;
143 | return;
144 | }
145 | }
146 | mCameraId = INVALID_CAMERA_ID;
147 | }
148 |
149 | private void openCamera() {
150 | if (mCamera != null) {
151 | releaseCamera();
152 | }
153 | mCamera = Camera.open(mCameraId);
154 | mCameraParameters = mCamera.getParameters();
155 | mPreviewSizes.clear();
156 | for (Camera.Size size : mCameraParameters.getSupportedPreviewSizes()) {
157 | // DLog.i("size->" + size.width + " " + size.height);
158 | mPreviewSizes.add(new CameraSize(size.width, size.height));
159 | }
160 |
161 | }
162 |
163 | private void adjustCameraParameters() {
164 | CameraSize suitableSize = getDealCameraSize(mCameraInfo.orientation);
165 | final CameraSize size = suitableSize.getSrcSize();
166 | mCameraParameters.setPreviewSize(size.getWidth(), size.getHeight());
167 | setAutoFocusInternal(true);
168 | mCamera.setParameters(mCameraParameters);
169 | mCamera.startPreview();
170 | }
171 |
172 | private void releaseCamera() {
173 | if (mCamera != null) {
174 | mCamera.release();
175 | mCamera = null;
176 | }
177 | }
178 |
179 | public void setCameraDisplayOrientation(Activity activity, Camera camera, Camera.CameraInfo info) {
180 | int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
181 | int degrees = 0;
182 | switch (rotation) {
183 | case Surface.ROTATION_0:
184 | degrees = 0;
185 | break;
186 | case Surface.ROTATION_90:
187 | degrees = 90;
188 | break;
189 | case Surface.ROTATION_180:
190 | degrees = 180;
191 | break;
192 | case Surface.ROTATION_270:
193 | degrees = 270;
194 | break;
195 | }
196 | int result;
197 | if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
198 | result = (info.orientation + degrees) % 360;
199 | result = (360 - result) % 360; // compensate the mirror
200 | } else {
201 | // back-facing
202 | result = (info.orientation - degrees + 360) % 360;
203 | }
204 | DLog.i("result: " + result);
205 | camera.setDisplayOrientation(result);
206 | }
207 |
208 | private boolean setAutoFocusInternal(boolean autoFocus) {
209 | if (isCameraOpened()) {
210 | final List modes = mCameraParameters.getSupportedFocusModes();
211 | if (autoFocus && modes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
212 | mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
213 | } else if (modes.contains(Camera.Parameters.FOCUS_MODE_FIXED)) {
214 | mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_FIXED);
215 | } else if (modes.contains(Camera.Parameters.FOCUS_MODE_INFINITY)) {
216 | mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_INFINITY);
217 | } else {
218 | mCameraParameters.setFocusMode(modes.get(0));
219 | }
220 | return true;
221 | } else {
222 | return false;
223 | }
224 | }
225 |
226 | boolean isCameraOpened() {
227 | return mCamera != null;
228 | }
229 |
230 | protected CameraSize getDealCameraSize(int rotation) {
231 | SortedSet greaterThanView = new TreeSet<>();
232 | List lessThanView = new ArrayList<>();
233 | WindowManager wm = (WindowManager) this
234 | .getSystemService(Context.WINDOW_SERVICE);
235 | Point point = new Point();
236 | if (wm == null) {
237 | point.x = 1080;
238 | point.y = 1920;
239 | } else {
240 | wm.getDefaultDisplay().getSize(point);
241 | }
242 | if (point.x > 700 && point.x < 800) {
243 | point.x = 720;
244 | point.y = 1280;
245 | } else if (point.x > 1000 && point.x < 1100) {
246 | point.x = 1080;
247 | point.y = 1920;
248 | }
249 | final int viewWidth = point.x;
250 | final int viewHeight = point.y;
251 | DLog.i("viewWidth> " + viewWidth + " viewHeight>> " + viewHeight);
252 | for (CameraSize size : mPreviewSizes) {
253 | if (rotation == 90 || rotation == 270) { // width > height normal
254 | if (size.getWidth() >= viewHeight && size.getHeight() >= viewWidth) {
255 | greaterThanView.add(new CameraSize(size.getHeight(), size.getWidth(), size));
256 | } else {
257 | lessThanView.add(new CameraSize(size.getHeight(), size.getWidth(), size));
258 | }
259 | } else { // width < height normal 0 180
260 | if (size.getWidth() >= viewWidth && size.getHeight() >= viewHeight) {
261 | greaterThanView.add(new CameraSize(size.getWidth(), size.getHeight(), size));
262 | } else {
263 | lessThanView.add(new CameraSize(size.getWidth(), size.getHeight(), size));
264 | }
265 | }
266 | }
267 | CameraSize cSize = null;
268 | if (greaterThanView.size() > 0) {
269 | cSize = greaterThanView.first();
270 | } else {
271 | int diffMinValue = Integer.MAX_VALUE;
272 | for (CameraSize size : lessThanView) {
273 | int diffWidth = Math.abs(viewWidth - size.getWidth());
274 | int diffHeight = Math.abs(viewHeight - size.getHeight());
275 | int diffValue = diffWidth + diffHeight;
276 | if (diffValue < diffMinValue) { // 找出差值最小的数
277 | diffMinValue = diffValue;
278 | cSize = size;
279 | }
280 | }
281 | if (cSize == null) {
282 | cSize = lessThanView.get(0);
283 | }
284 | }
285 | DLog.i("suitableSize>" + cSize.toString());
286 | return cSize;
287 | }
288 | }
289 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dming/testopengl/CameraRenderer.java:
--------------------------------------------------------------------------------
1 | package com.dming.testopengl;
2 |
3 | import android.content.Context;
4 | import android.opengl.GLES11Ext;
5 | import android.opengl.GLES20;
6 | import android.opengl.GLSurfaceView;
7 | import android.opengl.Matrix;
8 |
9 | import com.dming.testopengl.filter.BlurFilter;
10 | import com.dming.testopengl.filter.BurrFilter;
11 | import com.dming.testopengl.filter.CutApartFilter;
12 | import com.dming.testopengl.filter.EdgeFilter;
13 | import com.dming.testopengl.filter.IShader;
14 | import com.dming.testopengl.filter.LuminanceFilter;
15 | import com.dming.testopengl.filter.MultipleFilter;
16 | import com.dming.testopengl.filter.ShowGifFilter;
17 | import com.dming.testopengl.filter.ShowMovieFilter;
18 | import com.dming.testopengl.filter.SoulFilter;
19 | import com.dming.testopengl.utils.DLog;
20 |
21 | import javax.microedition.khronos.egl.EGLConfig;
22 | import javax.microedition.khronos.opengles.GL10;
23 |
24 | public class CameraRenderer implements GLSurfaceView.Renderer {
25 |
26 | private Context mContext;
27 |
28 | private int mTextureId;
29 | private int mWidth, mHeight;
30 |
31 | // private LineGraph mLineGraph;
32 | private CutApartFilter mCutApartFilter;
33 | private LuminanceFilter mLuminanceFilter;
34 | private BlurFilter mBlurFilter;
35 | private ShowGifFilter mShowGifFilter;
36 | private BurrFilter mBurrFilter;
37 | private ShowMovieFilter mShowMovieFilter;
38 | private MultipleFilter mMultipleFilter;
39 | private SoulFilter mSoulFilter;
40 | private EdgeFilter mEdgeFilter;
41 | //
42 | private IShader mCurShader;
43 | //
44 | private GLRunnable mGLRunnable;
45 | private GLSurfaceView mGLSurfaceView;
46 | //
47 | private int mPageIndex = -1;
48 | private float[] mTexMatrix = new float[16];
49 |
50 |
51 | CameraRenderer(GLSurfaceView glSurfaceView, GLRunnable glRunnable) {
52 | this.mContext = glSurfaceView.getContext();
53 | this.mGLSurfaceView = glSurfaceView;
54 | this.mGLRunnable = glRunnable;
55 | Matrix.setIdentityM(mTexMatrix, 0);
56 | }
57 |
58 | @Override
59 | public void onSurfaceCreated(GL10 gl, EGLConfig config) {
60 | DLog.i("onSurfaceCreated");
61 | GLES20.glClearColor(0f, 0f, 0f, 1f);
62 | mTextureId = createOESTexture();
63 | mGLRunnable.onSurfaceCreated(mTextureId);
64 | // mLineGraph = new LineGraph(mContext);
65 | mCutApartFilter = new CutApartFilter(mContext);
66 | mLuminanceFilter = new LuminanceFilter(mContext);
67 | mBlurFilter = new BlurFilter(mContext);
68 | mShowGifFilter = new ShowGifFilter(mContext);
69 | mBurrFilter = new BurrFilter(mContext);
70 | mShowMovieFilter = new ShowMovieFilter(mGLSurfaceView);
71 | mMultipleFilter = new MultipleFilter(mContext);
72 | mSoulFilter = new SoulFilter(mContext);
73 | mEdgeFilter = new EdgeFilter(mContext);
74 |
75 | chooseOneShaderOfNine(mPageIndex);
76 | }
77 |
78 | public void onSurfaceCreated(int width, int height) {
79 | if (this.mWidth != width || this.mHeight != height) {
80 | this.mWidth = width;
81 | this.mHeight = height;
82 | int w = mWidth / 3;
83 | int h = mHeight / 3;
84 | // mLineGraph.onChange(mWidth, mHeight);
85 | mCutApartFilter.onChange(w, h);
86 | mLuminanceFilter.onChange(w, h);
87 | mBlurFilter.onChange(w, h);
88 | mShowGifFilter.onChange(w, h);
89 | mBurrFilter.onChange(w, h);
90 | mShowMovieFilter.onChange(w, h);
91 | mMultipleFilter.onChange(w, h);
92 | mSoulFilter.onChange(w, h);
93 | mEdgeFilter.onChange(w, h);
94 | }
95 | }
96 |
97 | @Override
98 | public void onSurfaceChanged(GL10 gl, int width, int height) {
99 | DLog.i("onSurfaceChanged");
100 | GLES20.glViewport(0, 0, width, height);
101 | mGLRunnable.onSurfaceChanged(width, height);
102 | }
103 |
104 | @Override
105 | public void onDrawFrame(GL10 gl) {
106 | if (mWidth == 0 || mHeight == 0) {
107 | return;
108 | }
109 | long time = System.currentTimeMillis();
110 | int w = mWidth / 3;
111 | int h = mHeight / 3;
112 | GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
113 | // mLineGraph.onDraw(mTextureId, 0, 0, mWidth, mHeight);
114 | mCutApartFilter.onDraw(mTextureId, mTexMatrix, 0, h * 2, w, h + 1);
115 | mLuminanceFilter.onDraw(mTextureId, mTexMatrix, w, 0, w, h);
116 | mBurrFilter.onDraw(mTextureId, mTexMatrix, 0, h, w, h);
117 | mShowGifFilter.onDraw(mTextureId, mTexMatrix, w * 2, h * 2, w, h + 1);
118 | mBlurFilter.onDraw(mTextureId, mTexMatrix, w, h * 2, w, h + 1);
119 | mShowMovieFilter.onDraw(mTextureId, mTexMatrix, w * 2, h, w + 1, h);
120 | mMultipleFilter.onDraw(mTextureId, mTexMatrix, w, h, w, h);
121 | mSoulFilter.onDraw(mTextureId, mTexMatrix, 0, 0, w, h);
122 | mEdgeFilter.onDraw(mTextureId, mTexMatrix, w * 2, 0, w + 1, h);
123 | //
124 | if (mCurShader != null) {
125 | mCurShader.onDraw(mTextureId, mTexMatrix, 0, 0, mWidth, mHeight);
126 | }
127 | // DLog.i("time: " + (System.currentTimeMillis() - time));
128 | int err = GLES20.glGetError();
129 | if (err != 0) {
130 | DLog.i("gl err: " + err);
131 | }
132 | }
133 |
134 | public void setTexMatrix(float[] mTexMatrix) {
135 | this.mTexMatrix = mTexMatrix;
136 | }
137 |
138 | private static int createOESTexture() {
139 | int[] tex = new int[1];
140 | //生成一个纹理
141 | GLES20.glGenTextures(1, tex, 0);
142 | //将此纹理绑定到外部纹理上
143 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, tex[0]);
144 | //设置纹理过滤参数
145 | GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
146 | GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
147 | GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
148 | GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
149 | GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
150 | GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
151 | GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
152 | GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
153 | //解除纹理绑定
154 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0);
155 | return tex[0];
156 | }
157 |
158 | public void chooseOneShaderOfNine(int index) {
159 | if (mCurShader == null) {
160 | mPageIndex = index;
161 | if (index == 0) {
162 | mCurShader = mCutApartFilter;
163 | } else if (index == 1) {
164 | mCurShader = mBlurFilter;
165 | } else if (index == 2) {
166 | mCurShader = mShowGifFilter;
167 | } else if (index == 3) {
168 | mCurShader = mBurrFilter;
169 | } else if (index == 4) {
170 | mCurShader = mMultipleFilter;
171 | } else if (index == 5) {
172 | mCurShader = mShowMovieFilter;
173 | mShowMovieFilter.playVolume();
174 | } else if (index == 6) {
175 | mCurShader = mSoulFilter;
176 | } else if (index == 7) {
177 | mCurShader = mLuminanceFilter;
178 | } else if (index == 8) {
179 | mCurShader = mEdgeFilter;
180 | }
181 | } else {
182 | if (mPageIndex == 5) {
183 | mShowMovieFilter.stopVolume();
184 | }
185 | mPageIndex = -1;
186 | mCurShader = null;
187 | }
188 | }
189 |
190 | public void onDestroy() {
191 | this.mWidth = 0;
192 | this.mHeight = 0;
193 | this.mCurShader = null;
194 | // if (mLineGraph != null) {
195 | // mLineGraph.onDestroy();
196 | // mLineGraph = null;
197 | // }
198 | if (mCutApartFilter != null) {
199 | mCutApartFilter.onDestroy();
200 | mCutApartFilter = null;
201 | }
202 | if (mLuminanceFilter != null) {
203 | mLuminanceFilter.onDestroy();
204 | mLuminanceFilter = null;
205 | }
206 | if (mBlurFilter != null) {
207 | mBlurFilter.onDestroy();
208 | mBlurFilter = null;
209 | }
210 | if (mShowGifFilter != null) {
211 | mShowGifFilter.onDestroy();
212 | mShowGifFilter = null;
213 | }
214 | if (mBurrFilter != null) {
215 | mBurrFilter.onDestroy();
216 | mBurrFilter = null;
217 | }
218 | if (mShowMovieFilter != null) {
219 | mShowMovieFilter.onDestroy();
220 | mShowMovieFilter = null;
221 | }
222 | if (mMultipleFilter != null) {
223 | mMultipleFilter.onDestroy();
224 | mMultipleFilter = null;
225 | }
226 | if (mSoulFilter != null) {
227 | mSoulFilter.onDestroy();
228 | mSoulFilter = null;
229 | }
230 | if (mEdgeFilter != null) {
231 | mEdgeFilter.onDestroy();
232 | mEdgeFilter = null;
233 | }
234 | GLES20.glDeleteTextures(1, new int[]{mTextureId}, 0);
235 | }
236 |
237 |
238 | public interface GLRunnable {
239 | void onSurfaceCreated(int textureId);
240 |
241 | void onSurfaceChanged(int width, int height);
242 | }
243 |
244 | }
245 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dming/testopengl/CameraSize.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.dming.testopengl;
18 |
19 | import android.support.annotation.NonNull;
20 |
21 | /**
22 | * Immutable class for describing width and height dimensions in pixels.
23 | */
24 | public class CameraSize implements Comparable {
25 |
26 | private final int mWidth;
27 | private final int mHeight;
28 | private CameraSize mSrcSize;
29 |
30 | public CameraSize(int size1, int size2) {
31 | this.mWidth = size1;
32 | this.mHeight = size2;
33 | }
34 |
35 |
36 | public CameraSize(int size1, int size2, CameraSize mSrcSize) {
37 | this.mWidth = size1;
38 | this.mHeight = size2;
39 | this.mSrcSize = mSrcSize;
40 | }
41 |
42 |
43 | public int getWidth() {
44 | return mWidth;
45 | }
46 |
47 | public int getHeight() {
48 | return mHeight;
49 | }
50 |
51 | public CameraSize getSrcSize() {
52 | return mSrcSize;
53 | }
54 |
55 | @Override
56 | public boolean equals(Object o) {
57 | if (o == null) {
58 | return false;
59 | }
60 | if (this == o) {
61 | return true;
62 | }
63 | if (o instanceof CameraSize) {
64 | CameraSize size = (CameraSize) o;
65 | return mWidth == size.mWidth && mHeight == size.mHeight;
66 | }
67 | return false;
68 | }
69 |
70 | @Override
71 | public String toString() {
72 | return mWidth + "x" + mHeight;
73 | }
74 |
75 | @Override
76 | public int hashCode() {
77 | // assuming most sizes are <2^16, doing a rotate will give us perfect hashing
78 | return mHeight ^ ((mWidth << (Integer.SIZE / 2)) | (mWidth >>> (Integer.SIZE / 2)));
79 | }
80 |
81 | @Override
82 | public int compareTo(@NonNull CameraSize another) {
83 | return mWidth * mHeight - another.mWidth * another.mHeight;
84 | }
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dming/testopengl/LauncherActivity.java:
--------------------------------------------------------------------------------
1 | package com.dming.testopengl;
2 |
3 | import android.Manifest;
4 | import android.annotation.SuppressLint;
5 | import android.content.Intent;
6 | import android.content.pm.PackageManager;
7 | import android.os.Build;
8 | import android.os.Bundle;
9 | import android.support.annotation.NonNull;
10 | import android.support.annotation.Nullable;
11 | import android.support.v7.app.AppCompatActivity;
12 |
13 | public class LauncherActivity extends AppCompatActivity {
14 |
15 |
16 | @SuppressLint("ClickableViewAccessibility")
17 | @Override
18 | protected void onCreate(@Nullable Bundle savedInstanceState) {
19 | super.onCreate(savedInstanceState);
20 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
21 | getPackageManager().checkPermission(Manifest.permission.CAMERA, getPackageName())
22 | != PackageManager.PERMISSION_GRANTED) {
23 | requestPermissions(new String[]{Manifest.permission.CAMERA}, 666);
24 | } else {
25 | startActivity(new Intent(this, CameraActivity.class));
26 | finish();
27 | }
28 | }
29 |
30 | @Override
31 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
32 | super.onRequestPermissionsResult(requestCode, permissions, grantResults);
33 | if (requestCode == 666 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
34 | startActivity(new Intent(this, CameraActivity.class));
35 | finish();
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dming/testopengl/filter/BaseFilter.java:
--------------------------------------------------------------------------------
1 | package com.dming.testopengl.filter;
2 |
3 | import android.content.Context;
4 | import android.opengl.GLES11Ext;
5 | import android.opengl.GLES20;
6 | import android.opengl.Matrix;
7 |
8 | import com.dming.testopengl.R;
9 | import com.dming.testopengl.utils.ShaderHelper;
10 |
11 | import java.nio.FloatBuffer;
12 | import java.nio.ShortBuffer;
13 |
14 | public class BaseFilter implements IShader {
15 |
16 | protected ShortBuffer mIndexSB;
17 | protected FloatBuffer mTexFB;
18 | protected FloatBuffer mPosFB;
19 | protected static final short[] VERTEX_INDEX = {
20 | 0, 1, 3,
21 | 2, 3, 1
22 | };
23 | protected static final float[] VERTEX_POS = {
24 | -1, 1.0f, 0f,
25 | -1, -1.0f, 0f,
26 | 1, -1.0f, 0f,
27 | 1, 1.0f, 0f,
28 | };
29 | public static final float[] TEX_VERTEX = {
30 | 0, 1,
31 | 0, 0,
32 | 1, 0,
33 | 1, 1,
34 | };
35 |
36 | protected int mProgram;
37 | protected int mPosition;
38 | protected int mTextureCoordinate;
39 | protected int mImageOESTexture;
40 | protected int uMvpMatrix;
41 | protected int uTexMatrix;
42 | protected float[] mMvpMatrix = new float[16];
43 | protected Context mContext;
44 |
45 | public BaseFilter(Context context, int resFrgId) {
46 | this.mContext = context;
47 | mIndexSB = ShaderHelper.arrayToShortBuffer(VERTEX_INDEX);
48 | mPosFB = ShaderHelper.arrayToFloatBuffer(VERTEX_POS);
49 | mTexFB = ShaderHelper.arrayToFloatBuffer(TEX_VERTEX);
50 | mProgram = ShaderHelper.loadProgram(context, R.raw.process_ver, resFrgId);
51 | mPosition = GLES20.glGetAttribLocation(mProgram, "inputPosition");
52 | mTextureCoordinate = GLES20.glGetAttribLocation(mProgram, "inputTextureCoordinate");
53 | mImageOESTexture = GLES20.glGetUniformLocation(mProgram, "inputImageOESTexture");
54 | uMvpMatrix = GLES20.glGetUniformLocation(mProgram, "inputMatrix");
55 | uTexMatrix = GLES20.glGetUniformLocation(mProgram, "uTexMatrix");
56 | Matrix.setIdentityM(mMvpMatrix, 0);
57 | }
58 |
59 | @Override
60 | public void onChange(int width, int height) {
61 | }
62 |
63 | @Override
64 | public void onDraw(int textureId, float[] texMatrix, int x, int y, int width, int height) {
65 | onDraw(textureId, mMvpMatrix, texMatrix, x, y, width, height);
66 | }
67 |
68 | @Override
69 | public void onDraw(int textureId, float[] verMatrix, float[] texMatrix, int x, int y, int width, int height) {
70 | GLES20.glUseProgram(mProgram);
71 | GLES20.glEnableVertexAttribArray(mPosition);
72 | GLES20.glVertexAttribPointer(mPosition, 3,
73 | GLES20.GL_FLOAT, false, 0, mPosFB);
74 | GLES20.glEnableVertexAttribArray(mTextureCoordinate);
75 | GLES20.glVertexAttribPointer(mTextureCoordinate, 2,
76 | GLES20.GL_FLOAT, false, 0, mTexFB);
77 | GLES20.glUniformMatrix4fv(uMvpMatrix, 1, false, verMatrix, 0);
78 | GLES20.glUniformMatrix4fv(uTexMatrix, 1, false, texMatrix, 0);
79 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
80 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureId);
81 | GLES20.glUniform1i(mImageOESTexture, 0);
82 | GLES20.glViewport(x, y, width, height);
83 | GLES20.glDrawElements(GLES20.GL_TRIANGLES, VERTEX_INDEX.length,
84 | GLES20.GL_UNSIGNED_SHORT, mIndexSB);
85 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0);
86 | GLES20.glDisableVertexAttribArray(mPosition);
87 | GLES20.glDisableVertexAttribArray(mTextureCoordinate);
88 | GLES20.glUseProgram(0);
89 | }
90 |
91 | @Override
92 | public void onDestroy() {
93 | GLES20.glDeleteProgram(mProgram);
94 | }
95 |
96 | }
97 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dming/testopengl/filter/BlurFilter.java:
--------------------------------------------------------------------------------
1 | package com.dming.testopengl.filter;
2 |
3 | import android.content.Context;
4 | import android.opengl.GLES11Ext;
5 | import android.opengl.GLES20;
6 | import android.opengl.Matrix;
7 |
8 | import com.dming.testopengl.R;
9 | import com.dming.testopengl.utils.DLog;
10 | import com.dming.testopengl.utils.ShaderHelper;
11 |
12 | import java.nio.FloatBuffer;
13 | import java.nio.ShortBuffer;
14 |
15 | public class BlurFilter implements IShader {
16 |
17 | private final ShortBuffer mIndexSB;
18 | private FloatBuffer mTexFB;
19 | private final FloatBuffer mFBOTexFB;
20 | private FloatBuffer mPosFB;
21 | private FloatBuffer mFBOPosFB;
22 | private static final short[] VERTEX_INDEX = {
23 | 0, 1, 3,
24 | 2, 3, 1
25 | };
26 | private int mOESProgram;
27 | private int mOESImageTexture;
28 | private int mOESPosition;
29 | private int mOESTextureCoordinate;
30 | private int mOESIsVertical;
31 | private int mOESMatrix;
32 | private int uTexOESMatrix;
33 | // FBO
34 | private int[] mFrameBuffer = new int[1];
35 | private int[] mFrameBufferTexture = new int[1];
36 | private boolean isCreateFBO = false;
37 | private int mFBOWidth;
38 | private int mFBOHeight;
39 | //
40 | private float[] mIdentityMatrix = new float[4 * 4];
41 | //
42 | private int mProgram;
43 | private int mImageTexture;
44 | private int mPosition;
45 | private int mTextureCoordinate;
46 | private int mIsVertical;
47 | private int mMatrix;
48 | private int uTexMatrix;
49 |
50 | public BlurFilter(Context context) {
51 | mIndexSB = ShaderHelper.arrayToShortBuffer(VERTEX_INDEX);
52 | mOESProgram = ShaderHelper.loadProgram(context, R.raw.process_ver, R.raw.blur_frg);
53 | mOESPosition = GLES20.glGetAttribLocation(mOESProgram, "inputPosition");
54 | mOESTextureCoordinate = GLES20.glGetAttribLocation(mOESProgram, "inputTextureCoordinate");
55 | mOESImageTexture = GLES20.glGetUniformLocation(mOESProgram, "inputImageOESTexture");
56 | mOESIsVertical = GLES20.glGetUniformLocation(mOESProgram, "isVertical");
57 | mOESMatrix = GLES20.glGetUniformLocation(mOESProgram, "inputMatrix");
58 | uTexOESMatrix = GLES20.glGetUniformLocation(mOESProgram, "uTexMatrix");
59 |
60 | mProgram = ShaderHelper.loadProgram(context, R.raw.process_ver, R.raw.n_blur_frg);
61 | mPosition = GLES20.glGetAttribLocation(mProgram, "inputPosition");
62 | mTextureCoordinate = GLES20.glGetAttribLocation(mProgram, "inputTextureCoordinate");
63 | mImageTexture = GLES20.glGetUniformLocation(mProgram, "inputImageTexture");
64 | mIsVertical = GLES20.glGetUniformLocation(mProgram, "isVertical");
65 | mMatrix = GLES20.glGetUniformLocation(mProgram, "inputMatrix");
66 | uTexMatrix = GLES20.glGetUniformLocation(mProgram, "uTexMatrix");
67 | mPosFB = ShaderHelper.arrayToFloatBuffer(new float[]{
68 | -1, 1.0f, 0f,
69 | -1, -1.0f, 0f,
70 | 1, -1.0f, 0f,
71 | 1, 1.0f, 0f,
72 | });
73 | mFBOPosFB = ShaderHelper.arrayToFloatBuffer(new float[]{
74 | -1, 1.0f, 0f,
75 | -1, -1.0f, 0f,
76 | 1, -1.0f, 0f,
77 | 1, 1.0f, 0f,
78 | });
79 | mTexFB = ShaderHelper.arrayToFloatBuffer(new float[]{
80 | 0, 1,
81 | 0, 0,
82 | 1, 0,
83 | 1, 1,
84 | });
85 | mFBOTexFB = ShaderHelper.arrayToFloatBuffer(new float[]{
86 | 0, 1,
87 | 0, 0,
88 | 1, 0,
89 | 1, 1,
90 | });
91 | Matrix.setIdentityM(mIdentityMatrix, 0);
92 | }
93 |
94 | @Override
95 | public void onChange(int width, int height) {
96 | isCreateFBO = createFBO(width, height);
97 | }
98 |
99 | @Override
100 | public void onDraw(int textureId, float[] texMatrix, int x, int y, int width, int height) {
101 | onDraw(textureId, mIdentityMatrix, texMatrix, x, y, width, height);
102 | }
103 |
104 | @Override
105 | public void onDraw(int textureId, float[] verMatrix, float[] texMatrix, int x, int y, int width, int height) {
106 | if (isCreateFBO) {
107 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFrameBuffer[0]);
108 | drawOES(textureId, texMatrix, 0, 0, mFBOWidth, mFBOHeight);
109 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
110 | draw(mFrameBufferTexture[0], verMatrix, x, y, width, height);
111 | } else {
112 | drawOES(textureId, texMatrix, x, y, width, height);
113 | }
114 | }
115 |
116 | private void draw(int textureId, float[] texMatrix, int x, int y, int width, int height) {
117 | GLES20.glUseProgram(mProgram);
118 | GLES20.glEnableVertexAttribArray(mPosition);
119 | GLES20.glVertexAttribPointer(mPosition, 3,
120 | GLES20.GL_FLOAT, false, 0, mPosFB);
121 | GLES20.glEnableVertexAttribArray(mTextureCoordinate);
122 | GLES20.glVertexAttribPointer(mTextureCoordinate, 2,
123 | GLES20.GL_FLOAT, false, 0, mTexFB);
124 | GLES20.glUniformMatrix4fv(mMatrix, 1, false, mIdentityMatrix, 0);
125 | GLES20.glUniformMatrix4fv(uTexMatrix, 1, false, texMatrix, 0);
126 | GLES20.glUniform1i(mIsVertical, 0);
127 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
128 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
129 | GLES20.glUniform1i(mImageTexture, 0);
130 | GLES20.glViewport(x, y, width, height);
131 | GLES20.glDrawElements(GLES20.GL_TRIANGLES, VERTEX_INDEX.length,
132 | GLES20.GL_UNSIGNED_SHORT, mIndexSB);
133 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
134 | GLES20.glDisableVertexAttribArray(mPosition);
135 | GLES20.glDisableVertexAttribArray(mTextureCoordinate);
136 | GLES20.glDisableVertexAttribArray(mImageTexture);
137 | GLES20.glUseProgram(0);
138 | }
139 |
140 | private void drawOES(int textureId, float[] texMatrix, int x, int y, int width, int height) {
141 | GLES20.glUseProgram(mOESProgram);
142 | GLES20.glEnableVertexAttribArray(mOESPosition);
143 | GLES20.glVertexAttribPointer(mOESPosition, 3,
144 | GLES20.GL_FLOAT, false, 0, mFBOPosFB);
145 | GLES20.glEnableVertexAttribArray(mOESTextureCoordinate);
146 | GLES20.glVertexAttribPointer(mOESTextureCoordinate, 2,
147 | GLES20.GL_FLOAT, false, 0, mFBOTexFB);
148 | GLES20.glUniformMatrix4fv(mOESMatrix, 1, false, mIdentityMatrix, 0);
149 | GLES20.glUniformMatrix4fv(uTexOESMatrix, 1, false, texMatrix, 0);
150 | GLES20.glUniform1i(mOESIsVertical, 1);
151 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
152 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureId);
153 | GLES20.glUniform1i(mOESImageTexture, 0);
154 | GLES20.glViewport(x, y, width, height);
155 | GLES20.glDrawElements(GLES20.GL_TRIANGLES, VERTEX_INDEX.length,
156 | GLES20.GL_UNSIGNED_SHORT, mIndexSB);
157 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0);
158 | GLES20.glDisableVertexAttribArray(mOESPosition);
159 | GLES20.glDisableVertexAttribArray(mOESTextureCoordinate);
160 | GLES20.glDisableVertexAttribArray(mOESImageTexture);
161 | GLES20.glUseProgram(0);
162 | }
163 |
164 | private boolean createFBO(int width, int height) {
165 | mFBOWidth = width;
166 | mFBOHeight = height;
167 | GLES20.glGenFramebuffers(1, mFrameBuffer, 0);
168 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFrameBuffer[0]);
169 | GLES20.glGenTextures(1, mFrameBufferTexture, 0);
170 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mFrameBufferTexture[0]);
171 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
172 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
173 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
174 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
175 | GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0,
176 | GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
177 | GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0,
178 | GLES20.GL_TEXTURE_2D, mFrameBufferTexture[0], 0);
179 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
180 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
181 | if (GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER) != GLES20.GL_FRAMEBUFFER_COMPLETE) {
182 | GLES20.glDeleteFramebuffers(1, mFrameBuffer, 0);
183 | GLES20.glDeleteTextures(1, mFrameBufferTexture, 0);
184 | DLog.e("create framebuffer failed");
185 | return false;
186 | }
187 | // DLog.i("Java create framebuffer success: (" +
188 | // width + ", " + height + "), FB: " + mFrameBuffer[0] + " , Tex: " + mFrameBufferTexture[0]);
189 | return true;
190 | }
191 |
192 | @Override
193 | public void onDestroy() {
194 | GLES20.glDeleteProgram(mOESProgram);
195 | if (isCreateFBO) {
196 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFrameBuffer[0]);
197 | GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER,
198 | GLES20.GL_COLOR_ATTACHMENT0, GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0, 0);
199 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
200 | GLES20.glDeleteFramebuffers(1, mFrameBuffer, 0);
201 | GLES20.glDeleteTextures(1, mFrameBufferTexture, 0);
202 | }
203 | }
204 | }
205 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dming/testopengl/filter/BurrFilter.java:
--------------------------------------------------------------------------------
1 | package com.dming.testopengl.filter;
2 |
3 | import android.content.Context;
4 | import android.opengl.GLES11Ext;
5 | import android.opengl.GLES20;
6 |
7 | import com.dming.testopengl.R;
8 | import com.dming.testopengl.utils.GLInterpolator;
9 |
10 | public class BurrFilter extends BaseFilter {
11 |
12 | private int mTime;
13 | private float mCurTime = 0.0f;
14 | private GLInterpolator mGLInterpolator;
15 |
16 | public BurrFilter(Context context) {
17 | super(context, R.raw.burr_frg);
18 | mTime = GLES20.glGetUniformLocation(mProgram, "inputTime");
19 | mGLInterpolator = new GLInterpolator(300, 1.0f);
20 | }
21 |
22 | @Override
23 | public void onDraw(int textureId, float[] texMatrix, int x, int y, int width, int height) {
24 | GLES20.glUseProgram(mProgram);
25 | GLES20.glEnableVertexAttribArray(mPosition);
26 | GLES20.glVertexAttribPointer(mPosition, 3,
27 | GLES20.GL_FLOAT, false, 0, mPosFB);
28 | GLES20.glEnableVertexAttribArray(mTextureCoordinate);
29 | GLES20.glVertexAttribPointer(mTextureCoordinate, 2,
30 | GLES20.GL_FLOAT, false, 0, mTexFB);
31 | GLES20.glUniformMatrix4fv(uMvpMatrix, 1, false, mMvpMatrix, 0);
32 | GLES20.glUniformMatrix4fv(uTexMatrix, 1, false, texMatrix, 0);
33 | GLES20.glUniform1f(mTime, mCurTime);
34 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
35 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureId);
36 | GLES20.glUniform1i(mImageOESTexture, 0);
37 | GLES20.glViewport(x, y, width, height);
38 | GLES20.glDrawElements(GLES20.GL_TRIANGLES, VERTEX_INDEX.length,
39 | GLES20.GL_UNSIGNED_SHORT, mIndexSB);
40 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0);
41 | GLES20.glDisableVertexAttribArray(mPosition);
42 | GLES20.glDisableVertexAttribArray(mTextureCoordinate);
43 | GLES20.glDisableVertexAttribArray(mImageOESTexture);
44 | GLES20.glUseProgram(0);
45 | mCurTime = mGLInterpolator.getValue();
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dming/testopengl/filter/CutApartFilter.java:
--------------------------------------------------------------------------------
1 | package com.dming.testopengl.filter;
2 |
3 | import android.content.Context;
4 | import android.opengl.Matrix;
5 | import android.view.animation.DecelerateInterpolator;
6 |
7 | import com.dming.testopengl.R;
8 | import com.dming.testopengl.utils.GLInterpolator;
9 | import com.dming.testopengl.utils.ShaderHelper;
10 |
11 | import java.nio.FloatBuffer;
12 |
13 | public class CutApartFilter extends BaseFilter {
14 |
15 | private GLInterpolator mGLInterpolator;
16 | private DecelerateInterpolator mDecelerateInterpolator;
17 | private FloatBuffer mTexFB1;
18 | private FloatBuffer mTexFB2;
19 | private FloatBuffer mTexFB3;
20 | private float mTranslateY;
21 | private float mTranslateYY;
22 |
23 | public CutApartFilter(Context context) {
24 | super(context, R.raw.multiple_frg);
25 | mDecelerateInterpolator = new DecelerateInterpolator();
26 | mGLInterpolator = new GLInterpolator(4000, 1f, 0.0f);
27 | mTexFB1 = ShaderHelper.arrayToFloatBuffer(new float[]{
28 | 0, 1,
29 | 0, 0,
30 | 0.333f, 0,
31 | 0.333f, 1,
32 | });
33 | mTexFB2 = ShaderHelper.arrayToFloatBuffer(new float[]{
34 | 0.333f, 1,
35 | 0.333f, 0,
36 | 0.666f, 0,
37 | 0.666f, 1,
38 | });
39 | mTexFB3 = ShaderHelper.arrayToFloatBuffer(new float[]{
40 | 0.666f, 1,
41 | 0.666f, 0,
42 | 1, 0,
43 | 1, 1,
44 | });
45 | }
46 |
47 | @Override
48 | public void onDraw(int textureId, float[] texMatrix, int x, int y, int width, int height) {
49 | float value = mGLInterpolator.getValue();
50 | if (value <= 0.25) {
51 | mTranslateY = mDecelerateInterpolator.getInterpolation(1 - value / 0.25f) * 2;
52 | mTranslateYY = -2 + mTranslateY;
53 | } else if (value >= 0.5 && value <= 0.75) {
54 | mTranslateY = -mDecelerateInterpolator.getInterpolation((value - 0.5f) / 0.25f) * 2;
55 | mTranslateYY = 2 + mTranslateY;
56 | } else {
57 | mTranslateY = 0;
58 | mTranslateYY = 0;
59 | }
60 |
61 | mTexFB = mTexFB1;
62 | int w = width / 3;
63 | Matrix.setIdentityM(mMvpMatrix, 0);
64 | super.onDraw(textureId, mMvpMatrix, texMatrix, x, y, w, height);
65 | //
66 | mTexFB = mTexFB2;
67 | if (mTranslateY != 0) {
68 | Matrix.translateM(mMvpMatrix, 0, 0, mTranslateYY, 0);
69 | super.onDraw(textureId, mMvpMatrix, texMatrix, x + w, y, w, height);
70 | }
71 | Matrix.setIdentityM(mMvpMatrix, 0);
72 | Matrix.translateM(mMvpMatrix, 0, 0, mTranslateY, 0);
73 | super.onDraw(textureId, mMvpMatrix, texMatrix, x + w, y, w, height);
74 | //
75 | mTexFB = mTexFB3;
76 | Matrix.setIdentityM(mMvpMatrix, 0);
77 | super.onDraw(textureId, mMvpMatrix, texMatrix, x + w + w, y, w, height);
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dming/testopengl/filter/EdgeFilter.java:
--------------------------------------------------------------------------------
1 | package com.dming.testopengl.filter;
2 |
3 | import android.content.Context;
4 | import android.opengl.GLES20;
5 |
6 | import com.dming.testopengl.R;
7 |
8 | public class EdgeFilter extends BaseFilter {
9 |
10 | public EdgeFilter(Context context) {
11 | super(context, R.raw.edge_frg);
12 | }
13 |
14 | @Override
15 | public void onDraw(int textureId, float[] texMatrix, int x, int y, int width, int height) {
16 | GLES20.glEnable(GLES20.GL_BLEND);
17 | GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
18 | super.onDraw(textureId, texMatrix, x, y, width, height);
19 | GLES20.glDisable(GLES20.GL_BLEND);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dming/testopengl/filter/IShader.java:
--------------------------------------------------------------------------------
1 | package com.dming.testopengl.filter;
2 |
3 | public interface IShader {
4 |
5 | void onChange(int width, int height);
6 |
7 | void onDraw(int textureId, float[] texMatrix, int x, int y, int width, int height);
8 |
9 | void onDraw(int textureId, float[] verMatrix, float[] texMatrix, int x, int y, int width, int height);
10 |
11 | void onDestroy();
12 | }
13 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dming/testopengl/filter/LuminanceFilter.java:
--------------------------------------------------------------------------------
1 | package com.dming.testopengl.filter;
2 |
3 | import android.content.Context;
4 |
5 | import com.dming.testopengl.R;
6 |
7 | public class LuminanceFilter extends BaseFilter {
8 |
9 | public LuminanceFilter(Context context) {
10 | super(context, R.raw.luminance_frg);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dming/testopengl/filter/MultipleFilter.java:
--------------------------------------------------------------------------------
1 | package com.dming.testopengl.filter;
2 |
3 | import android.content.Context;
4 |
5 | import com.dming.testopengl.R;
6 | import com.dming.testopengl.utils.ShaderHelper;
7 |
8 | public class MultipleFilter extends BaseFilter {
9 |
10 | public MultipleFilter(Context context) {
11 | super(context, R.raw.multiple_frg);
12 | mTexFB = ShaderHelper.arrayToFloatBuffer(new float[]{
13 | 0, 0.667f,
14 | 0, 0.334f,
15 | 1, 0.334f,
16 | 1, 0.667f,
17 | });
18 | }
19 |
20 |
21 | @Override
22 | public void onDraw(int textureId, float[] texMatrix, int x, int y, int width, int height) {
23 | int h = height / 3;
24 | super.onDraw(textureId, texMatrix, x, y, width, h);
25 | super.onDraw(textureId, texMatrix, x, y + h, width, height - h - h);
26 | super.onDraw(textureId, texMatrix, x, y + height - h, width, h);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dming/testopengl/filter/ShowGifFilter.java:
--------------------------------------------------------------------------------
1 | package com.dming.testopengl.filter;
2 |
3 | import android.content.Context;
4 | import android.opengl.GLES20;
5 |
6 | import com.dming.testgif.DLog;
7 | import com.dming.testgif.FGLUtils;
8 | import com.dming.testgif.GifFilter;
9 | import com.dming.testgif.GifPlayer;
10 | import com.dming.testopengl.R;
11 |
12 | public class ShowGifFilter extends BaseFilter implements GifPlayer.OnGifListener {
13 |
14 | private GifPlayer mGifPlayer;
15 | private GifFilter mGifFilter;
16 | private int mTexture;
17 | private float mGifRatio;
18 |
19 | public ShowGifFilter(Context context) {
20 | super(context, R.raw.sharpen_frg);
21 | mTexture = FGLUtils.createTexture();
22 | mGifFilter = new GifFilter(context);
23 | mGifPlayer = new GifPlayer(mTexture);
24 | mGifPlayer.setOnGifListener(this);
25 | mGifPlayer.assetPlay(mContext, "mogutou.gif");
26 | }
27 |
28 | public void resume() {
29 | mGifPlayer.resume();
30 | }
31 |
32 | public void pause() {
33 | mGifPlayer.pause();
34 | }
35 |
36 | @Override
37 | public void onDraw(int textureId, float[] texMatrix, int x, int y, int width, int height) {
38 | GLES20.glEnable(GLES20.GL_BLEND);
39 | GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);// 后面透明
40 | super.onDraw(textureId, texMatrix, x, y, width, height);
41 | mGifFilter.onDraw(mTexture, x, y, (int) (mGifRatio * height / 3), height / 3);
42 | GLES20.glDisable(GLES20.GL_BLEND);
43 | }
44 |
45 | @Override
46 | public void onDestroy() {
47 | super.onDestroy();
48 | mGifFilter.onDestroy();
49 | mGifPlayer.destroy();
50 | }
51 |
52 | @Override
53 | public void start() {
54 | DLog.i("start>>>");
55 | }
56 |
57 | @Override
58 | public void size(int width, int height) {
59 | mGifRatio = 1.0f * width / height;
60 | }
61 |
62 | @Override
63 | public void update() {
64 | // DLog.i("update>>>");
65 | }
66 |
67 | @Override
68 | public void end() {
69 | DLog.i("end>>>");
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dming/testopengl/filter/ShowMovieFilter.java:
--------------------------------------------------------------------------------
1 | package com.dming.testopengl.filter;
2 |
3 | import android.content.res.AssetFileDescriptor;
4 | import android.graphics.SurfaceTexture;
5 | import android.media.MediaPlayer;
6 | import android.opengl.GLES11Ext;
7 | import android.opengl.GLES20;
8 | import android.opengl.GLSurfaceView;
9 | import android.opengl.Matrix;
10 | import android.view.Surface;
11 |
12 | import com.dming.testopengl.R;
13 | import com.dming.testopengl.utils.DLog;
14 | import com.dming.testopengl.utils.ShaderHelper;
15 |
16 | import java.io.IOException;
17 | import java.nio.FloatBuffer;
18 |
19 | import javax.microedition.khronos.opengles.GL10;
20 |
21 | public class ShowMovieFilter extends BaseFilter {
22 |
23 | private int mIsVideo;
24 | private FloatBuffer mVideoTexFB;
25 | //
26 | private MediaPlayer mPlayer;
27 | private Surface mSurface;
28 | private SurfaceTexture mSurfaceTexture;
29 | private int mOESVideoTexture = -1;
30 | private boolean mCanUpdate = false;
31 | private float[] mIdentityMatrix = new float[4 * 4];
32 |
33 | public ShowMovieFilter(GLSurfaceView glSurfaceView) {
34 | super(glSurfaceView.getContext(), R.raw.animation_frg);
35 | mIsVideo = GLES20.glGetUniformLocation(mProgram, "isVideo");
36 | // 一般编/解码器都有16位对齐的处理(有未经证实的说法,也存在32位、64位对齐的),否则会产生绿边问题。
37 | // 由于MediaPlayer在某些机型硬解码出现数据对齐问题,产生绿边,MediaPlayer是高级API,无法解决;
38 | // 这里投机不显示边缘,个人认为要更好解决就是算图像宽度是不是16的倍数,最好32倍数;然后截取
39 | // 这里就是简单截取,0 - 0.9
40 | mVideoTexFB = ShaderHelper.arrayToFloatBuffer(new float[]{
41 | 0f, 1f,
42 | 0.9f, 1f,
43 | 0.9f, 0f,
44 | 0f, 0f,
45 | });
46 | initPlayer(glSurfaceView);
47 | Matrix.setIdentityM(mIdentityMatrix, 0);
48 | }
49 |
50 | @Override
51 | public void onDraw(int textureId, float[] texMatrix, int x, int y, int width, int height) {
52 | if (mCanUpdate) {
53 | GLES20.glEnable(GLES20.GL_BLEND);
54 | GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
55 |
56 | GLES20.glUseProgram(mProgram);
57 | GLES20.glEnableVertexAttribArray(mPosition);
58 | GLES20.glVertexAttribPointer(mPosition, 3,
59 | GLES20.GL_FLOAT, false, 0, mPosFB);
60 | GLES20.glEnableVertexAttribArray(mTextureCoordinate);
61 | GLES20.glVertexAttribPointer(mTextureCoordinate, 2,
62 | GLES20.GL_FLOAT, false, 0, mTexFB);
63 | GLES20.glUniformMatrix4fv(uMvpMatrix, 1, false, mMvpMatrix, 0);
64 | GLES20.glUniformMatrix4fv(uTexMatrix, 1, false, texMatrix, 0);
65 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
66 | GLES20.glUniform1i(mImageOESTexture, 0);
67 |
68 | GLES20.glUniform1i(mIsVideo, 0);
69 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureId);
70 |
71 | GLES20.glViewport(x, y, width, height);
72 | GLES20.glDrawElements(GLES20.GL_TRIANGLES, VERTEX_INDEX.length,
73 | GLES20.GL_UNSIGNED_SHORT, mIndexSB);
74 |
75 | GLES20.glVertexAttribPointer(mTextureCoordinate, 2,
76 | GLES20.GL_FLOAT, false, 0, mVideoTexFB);
77 | GLES20.glUniform1i(mIsVideo, 1);
78 | GLES20.glUniformMatrix4fv(uTexMatrix, 1, false, mIdentityMatrix, 0);
79 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mOESVideoTexture);
80 | GLES20.glDrawElements(GLES20.GL_TRIANGLES, VERTEX_INDEX.length,
81 | GLES20.GL_UNSIGNED_SHORT, mIndexSB);
82 |
83 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0);
84 |
85 | GLES20.glDisableVertexAttribArray(mPosition);
86 | GLES20.glDisableVertexAttribArray(mTextureCoordinate);
87 | GLES20.glUseProgram(0);
88 |
89 | GLES20.glDisable(GLES20.GL_BLEND);
90 | } else {
91 | super.onDraw(textureId, texMatrix, x, y, width, height);
92 | }
93 |
94 | }
95 |
96 | @Override
97 | public void onDestroy() {
98 | release();
99 | GLES20.glDeleteBuffers(1, new int[]{mOESVideoTexture}, 0);
100 | super.onDestroy();
101 | }
102 |
103 | public void playVolume() {
104 | DLog.i("playVolume>>>");
105 | if (mPlayer != null) {
106 | mPlayer.setVolume(1, 1);
107 | }
108 | }
109 |
110 | public void stopVolume() {
111 | DLog.i("stopVolume");
112 | if (mPlayer != null) {
113 | mPlayer.setVolume(0, 0);
114 | }
115 | }
116 |
117 |
118 | private void initPlayer(final GLSurfaceView glSurfaceView) {
119 | DLog.i("initPlayer>>>");
120 | mPlayer = new MediaPlayer();
121 | mOESVideoTexture = createOESTexture();
122 | mSurfaceTexture = new SurfaceTexture(mOESVideoTexture);
123 | mSurfaceTexture.setOnFrameAvailableListener(new SurfaceTexture.OnFrameAvailableListener() {
124 | @Override
125 | public void onFrameAvailable(final SurfaceTexture surfaceTexture) {
126 | if (mSurfaceTexture != null) {
127 | glSurfaceView.queueEvent(new Runnable() {
128 | @Override
129 | public void run() {
130 | if (mSurfaceTexture != null) {
131 | mSurfaceTexture.updateTexImage();
132 | mCanUpdate = true;
133 | }
134 | }
135 | });
136 | }
137 | }
138 | });
139 | mSurface = new Surface(mSurfaceTexture);
140 | mPlayer.setSurface(mSurface);
141 | DLog.i("Video oesTexture: " + mOESVideoTexture);
142 | mPlayer.reset();
143 | try {
144 | AssetFileDescriptor afd = this.mContext.getAssets().openFd("animation.mp4");
145 | mPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
146 | mPlayer.prepare();
147 | } catch (IOException e) {
148 | DLog.i("Play Error!!!");
149 | }
150 | mPlayer.setLooping(true);
151 | //
152 | mPlayer.setVolume(0, 0);
153 | mPlayer.start();
154 | }
155 |
156 |
157 | private void release() {
158 | DLog.i("release>>>" + mPlayer);
159 | mPlayer.release();
160 | SurfaceTexture surfaceTexture = mSurfaceTexture;
161 | if (mSurfaceTexture != null) {
162 | mSurfaceTexture = null;
163 | surfaceTexture.setOnFrameAvailableListener(null);
164 | surfaceTexture.release();
165 | }
166 | mSurface.release();
167 | mPlayer = null;
168 | }
169 |
170 |
171 | public int createOESTexture() {
172 | int[] tex = new int[1];
173 | //生成一个纹理
174 | GLES20.glGenTextures(1, tex, 0);
175 | //将此纹理绑定到外部纹理上
176 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, tex[0]);
177 | //设置纹理过滤参数
178 | GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
179 | GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
180 | GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
181 | GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
182 | GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
183 | GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
184 | GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
185 | GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
186 | //解除纹理绑定
187 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0);
188 | return tex[0];
189 | }
190 | }
191 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dming/testopengl/filter/SoulFilter.java:
--------------------------------------------------------------------------------
1 | package com.dming.testopengl.filter;
2 |
3 | import android.content.Context;
4 | import android.opengl.GLES11Ext;
5 | import android.opengl.GLES20;
6 | import android.opengl.Matrix;
7 |
8 | import com.dming.testopengl.R;
9 | import com.dming.testopengl.utils.GLInterpolator;
10 |
11 | public class SoulFilter extends BaseFilter {
12 |
13 | private int mAlpha;
14 | private float mScaleRatio = 1.0f;
15 | private GLInterpolator mGLInterpolator;
16 |
17 | public SoulFilter(Context context) {
18 | super(context, R.raw.soul_frg);
19 | mGLInterpolator = new GLInterpolator(300, 0.3f,1.0f);
20 | mAlpha = GLES20.glGetUniformLocation(mProgram, "inputAlpha");
21 | }
22 |
23 | @Override
24 | public void onDraw(int textureId, float[] texMatrix, int x, int y, int width, int height) {
25 | GLES20.glEnable(GLES20.GL_BLEND);
26 | GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
27 |
28 | Matrix.setIdentityM(mMvpMatrix, 0);
29 |
30 | GLES20.glUseProgram(mProgram);
31 | GLES20.glEnableVertexAttribArray(mPosition);
32 | GLES20.glVertexAttribPointer(mPosition, 3,
33 | GLES20.GL_FLOAT, false, 0, mPosFB);
34 | GLES20.glEnableVertexAttribArray(mTextureCoordinate);
35 | GLES20.glVertexAttribPointer(mTextureCoordinate, 2,
36 | GLES20.GL_FLOAT, false, 0, mTexFB);
37 |
38 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
39 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureId);
40 | GLES20.glUniform1i(mImageOESTexture, 0);
41 | GLES20.glViewport(x, y, width, height);
42 |
43 | Matrix.scaleM(mMvpMatrix, 0, 1f, 1.0f, 1f);
44 | GLES20.glUniformMatrix4fv(uMvpMatrix, 1, false, mMvpMatrix, 0);
45 | GLES20.glUniformMatrix4fv(uTexMatrix, 1, false, texMatrix, 0);
46 | GLES20.glUniform1f(mAlpha, 1.0f);
47 | GLES20.glDrawElements(GLES20.GL_TRIANGLES, VERTEX_INDEX.length,
48 | GLES20.GL_UNSIGNED_SHORT, mIndexSB);
49 |
50 | Matrix.scaleM(mMvpMatrix, 0, mScaleRatio, mScaleRatio, 1f);
51 | GLES20.glUniformMatrix4fv(uMvpMatrix, 1, false, mMvpMatrix, 0);
52 | GLES20.glUniform1f(mAlpha, 0.3f);
53 | GLES20.glDrawElements(GLES20.GL_TRIANGLES, VERTEX_INDEX.length,
54 | GLES20.GL_UNSIGNED_SHORT, mIndexSB);
55 |
56 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0);
57 | GLES20.glDisableVertexAttribArray(mPosition);
58 | GLES20.glDisableVertexAttribArray(mTextureCoordinate);
59 | GLES20.glDisableVertexAttribArray(mImageOESTexture);
60 | GLES20.glUseProgram(0);
61 | GLES20.glDisable(GLES20.GL_BLEND);
62 |
63 | mScaleRatio = mGLInterpolator.getValue();
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dming/testopengl/utils/DLog.java:
--------------------------------------------------------------------------------
1 | package com.dming.testopengl.utils;
2 |
3 | import android.util.Log;
4 |
5 | import com.dming.testopengl.BuildConfig;
6 |
7 |
8 | /**
9 | * 简单日志类,方便
10 | * Created by DMing on 2017/9/19.
11 | */
12 |
13 | public class DLog {
14 |
15 | private static String TAG = "DMUI";
16 |
17 | public static void d(String msg){
18 | if (BuildConfig.DEBUG) Log.d(TAG,msg);
19 | }
20 |
21 | public static void i(String msg){
22 | if (BuildConfig.DEBUG) Log.i(TAG,msg);
23 | }
24 |
25 | public static void e(String msg){
26 | if (BuildConfig.DEBUG) Log.e(TAG,msg);
27 | }
28 |
29 | @SuppressWarnings("unused")
30 | public static void d(String tagNull, String msg) {
31 | d(msg);
32 | }
33 |
34 | @SuppressWarnings("unused")
35 | public static void i(String tagNull, String msg) {
36 | i(msg);
37 | }
38 |
39 | @SuppressWarnings("unused")
40 | public static void e(String tagNull, String msg) {
41 | e(msg);
42 | }
43 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/dming/testopengl/utils/FGLUtils.java:
--------------------------------------------------------------------------------
1 | package com.dming.testopengl.utils;
2 |
3 | import android.opengl.GLES11Ext;
4 | import android.opengl.GLES20;
5 |
6 | import javax.microedition.khronos.opengles.GL10;
7 |
8 | public class FGLUtils {
9 |
10 | public static int[] createFBO(int width, int height) {
11 | int[] mFrameBuffer = new int[1];
12 | int[] mFrameBufferTexture = new int[1];
13 | GLES20.glGenFramebuffers(1, mFrameBuffer, 0);
14 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFrameBuffer[0]);
15 | GLES20.glGenTextures(1, mFrameBufferTexture, 0);
16 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mFrameBufferTexture[0]);
17 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
18 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
19 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
20 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
21 | GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0,
22 | GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
23 | GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0,
24 | GLES20.GL_TEXTURE_2D, mFrameBufferTexture[0], 0);
25 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
26 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
27 | if (GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER) != GLES20.GL_FRAMEBUFFER_COMPLETE) {
28 | GLES20.glDeleteFramebuffers(1, mFrameBuffer, 0);
29 | GLES20.glDeleteTextures(1, mFrameBufferTexture, 0);
30 | DLog.e("create framebuffer failed");
31 | return null;
32 | }
33 | DLog.i("Java create framebuffer success: (" +
34 | width + ", " + height + "), FB: " + mFrameBuffer[0] + " , Tex: " + mFrameBufferTexture[0]);
35 | return new int[]{mFrameBuffer[0], mFrameBufferTexture[0]};
36 | }
37 |
38 | public static int createOESTexture() {
39 | int[] tex = new int[1];
40 | //生成一个纹理
41 | GLES20.glGenTextures(1, tex, 0);
42 | //将此纹理绑定到外部纹理上
43 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, tex[0]);
44 | //设置纹理过滤参数
45 | GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
46 | GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
47 | GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
48 | GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
49 | GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
50 | GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
51 | GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
52 | GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
53 | //解除纹理绑定
54 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0);
55 | return tex[0];
56 | }
57 |
58 | public static int createTexture() {
59 | int[] tex = new int[1];
60 | GLES20.glGenTextures(1, tex, 0);
61 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tex[0]);
62 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
63 | GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
64 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
65 | GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
66 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
67 | GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
68 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
69 | GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
70 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
71 | return tex[0];
72 | }
73 |
74 | public static void glCheckErr() {
75 | int err = GLES20.glGetError();
76 | DLog.i("checkErr: " + err);
77 | }
78 |
79 | public static void glCheckErr(String tag) {
80 | int err = GLES20.glGetError();
81 | if (err != 0) {
82 | DLog.i(tag + " > checkErr: " + err);
83 | }
84 | }
85 |
86 | public static void glCheckErr(int tag) {
87 | int err = GLES20.glGetError();
88 | DLog.i(tag + " > checkErr: " + err);
89 | }
90 |
91 | }
92 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dming/testopengl/utils/GLInterpolator.java:
--------------------------------------------------------------------------------
1 | package com.dming.testopengl.utils;
2 |
3 | /**
4 | * ms
5 | */
6 | public class GLInterpolator {
7 |
8 | private int mTimeSpan;
9 | private float mMaxValue = 1.0f;
10 | private float mMinValue = 0.0f;
11 | private long mLastTime = 0;
12 |
13 | public GLInterpolator(int timeSpan) {
14 | mTimeSpan = timeSpan;
15 | }
16 |
17 | public GLInterpolator(int timeSpan, float maxValue) {
18 | mTimeSpan = timeSpan;
19 | mMaxValue = maxValue;
20 | }
21 |
22 | public GLInterpolator(int timeSpan, float maxRelativeValue, float minValue) {
23 | mTimeSpan = timeSpan;
24 | mMaxValue = maxRelativeValue;
25 | mMinValue = minValue;
26 | }
27 |
28 | public float getValue() {
29 | long time = System.currentTimeMillis();
30 | if (mLastTime == 0) {
31 | mLastTime = time;
32 | }
33 | long diff = time - mLastTime;
34 | if (diff >= mTimeSpan * 10) {
35 | mLastTime = time;
36 | }
37 | int t = (int) (diff % mTimeSpan);
38 | return mMinValue + mMaxValue * t / mTimeSpan;
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dming/testopengl/utils/ShaderHelper.java:
--------------------------------------------------------------------------------
1 | package com.dming.testopengl.utils;
2 |
3 | import android.content.Context;
4 | import android.opengl.GLES20;
5 |
6 | import java.io.IOException;
7 | import java.io.InputStream;
8 | import java.nio.ByteBuffer;
9 | import java.nio.ByteOrder;
10 | import java.nio.FloatBuffer;
11 | import java.nio.ShortBuffer;
12 |
13 | public class ShaderHelper {
14 |
15 | /**
16 | * 编译顶点着色器
17 | *
18 | * @param shaderCode 编译代码
19 | * @return 着色器对象ID
20 | */
21 | public static int compileVertexShader(String shaderCode) {
22 | return compileShader(GLES20.GL_VERTEX_SHADER, shaderCode);
23 | }
24 |
25 | /**
26 | * 编译片段着色器
27 | *
28 | * @param shaderCode 编译代码
29 | * @return 着色器对象ID
30 | */
31 | public static int compileFragmentShader(String shaderCode) {
32 | return compileShader(GLES20.GL_FRAGMENT_SHADER, shaderCode);
33 | }
34 |
35 | /**
36 | * 编译片段着色器
37 | *
38 | * @param type 着色器类型
39 | * @param shaderCode 编译代码
40 | * @return 着色器对象ID
41 | */
42 | private static int compileShader(int type, String shaderCode) {
43 | // 1.创建一个新的着色器对象
44 | final int shaderObjectId = GLES20.glCreateShader(type);
45 |
46 | // 2.获取创建状态
47 | if (shaderObjectId == 0) {
48 | // 在OpenGL中,都是通过整型值去作为OpenGL对象的引用。之后进行操作的时候都是将这个整型值传回给OpenGL进行操作。
49 | // 返回值0代表着创建对象失败。
50 | DLog.e("Could not create new shader.");
51 | return 0;
52 | }
53 |
54 | // 3.将着色器代码上传到着色器对象中
55 | GLES20.glShaderSource(shaderObjectId, shaderCode);
56 |
57 | // 4.编译着色器对象
58 | GLES20.glCompileShader(shaderObjectId);
59 |
60 | // 5.获取编译状态:OpenGL将想要获取的值放入长度为1的数组的首位
61 | final int[] compileStatus = new int[1];
62 | GLES20.glGetShaderiv(shaderObjectId, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
63 |
64 | // 打印编译的着色器信息
65 | // DLog.i( "Results of compiling source:" + "\n" + shaderCode + "\n:"
66 | // + GLES20.glGetShaderInfoLog(shaderObjectId));
67 |
68 | // 6.验证编译状态
69 | if (compileStatus[0] == 0) {
70 | // 如果编译失败,则删除创建的着色器对象
71 | GLES20.glDeleteShader(shaderObjectId);
72 | DLog.e("Compilation of shader failed.");
73 | // 7.返回着色器对象:失败,为0
74 | return 0;
75 | }
76 |
77 | // 7.返回着色器对象:成功,非0
78 | return shaderObjectId;
79 | }
80 |
81 | /**
82 | * 创建OpenGL程序:通过链接顶点着色器、片段着色器
83 | *
84 | * @param vertexShaderId 顶点着色器ID
85 | * @param fragmentShaderId 片段着色器ID
86 | * @return OpenGL程序ID
87 | */
88 | public static int linkProgram(int vertexShaderId, int fragmentShaderId) {
89 |
90 | // 1.创建一个OpenGL程序对象
91 | final int programObjectId = GLES20.glCreateProgram();
92 |
93 | // 2.获取创建状态
94 | if (programObjectId == 0) {
95 | DLog.e("Could not create new program");
96 | return 0;
97 | }
98 |
99 | // 3.将顶点着色器依附到OpenGL程序对象
100 | GLES20.glAttachShader(programObjectId, vertexShaderId);
101 | // 3.将片段着色器依附到OpenGL程序对象
102 | GLES20.glAttachShader(programObjectId, fragmentShaderId);
103 |
104 | // 4.将两个着色器链接到OpenGL程序对象
105 | GLES20.glLinkProgram(programObjectId);
106 |
107 | // 5.获取链接状态:OpenGL将想要获取的值放入长度为1的数组的首位
108 | final int[] linkStatus = new int[1];
109 | GLES20.glGetProgramiv(programObjectId, GLES20.GL_LINK_STATUS, linkStatus, 0);
110 |
111 | // 打印链接信息
112 | // DLog.i("Results of linking program:\n"
113 | // + GLES20.glGetProgramInfoLog(programObjectId));
114 |
115 | // 6.验证链接状态
116 | if (linkStatus[0] == 0) {
117 | // 链接失败则删除程序对象
118 | GLES20.glDeleteProgram(programObjectId);
119 | DLog.e("Linking of program failed.");
120 | // 7.返回程序对象:失败,为0
121 | return 0;
122 | }
123 | GLES20.glDeleteShader(vertexShaderId);
124 | GLES20.glDeleteShader(fragmentShaderId);
125 | // 7.返回程序对象:成功,非0
126 | return programObjectId;
127 | }
128 |
129 | /**
130 | * 验证OpenGL程序对象状态
131 | *
132 | * @param programObjectId OpenGL程序ID
133 | * @return 是否可用
134 | */
135 | private static boolean validateProgram(int programObjectId) {
136 | GLES20.glValidateProgram(programObjectId);
137 |
138 | final int[] validateStatus = new int[1];
139 | GLES20.glGetProgramiv(programObjectId, GLES20.GL_VALIDATE_STATUS, validateStatus, 0);
140 | DLog.i("Results of validating program: " + validateStatus[0]
141 | + "\nLog:" + GLES20.glGetProgramInfoLog(programObjectId));
142 |
143 | return validateStatus[0] != 0;
144 | }
145 |
146 | public static String readResource(Context context, int id) {
147 | InputStream inputStream = context.getResources().openRawResource(id);
148 | StringBuilder out = new StringBuilder();
149 | byte[] b = new byte[4096];
150 | try {
151 | for (int n; (n = inputStream.read(b)) != -1; ) {
152 | out.append(new String(b, 0, n));
153 | }
154 | } catch (IOException io) {
155 | }
156 | return out.toString();
157 | }
158 |
159 | /**
160 | * 创建OpenGL程序对象
161 | *
162 | * @param vertexShaderRes 顶点着色器代码
163 | * @param fragmentShaderRes 片段着色器代码
164 | */
165 | public static int loadProgram(Context context, int vertexShaderRes, int fragmentShaderRes) {
166 | final int vertexShaderId = ShaderHelper.compileVertexShader(readResource(context, vertexShaderRes));
167 | final int fragmentShaderId = ShaderHelper.compileFragmentShader(readResource(context, fragmentShaderRes));
168 | return ShaderHelper.linkProgram(vertexShaderId, fragmentShaderId);
169 | }
170 |
171 | public static FloatBuffer arrayToFloatBuffer(float[] fArray) {
172 | FloatBuffer fBuffer = ByteBuffer.allocateDirect(fArray.length * 4)
173 | .order(ByteOrder.nativeOrder())
174 | .asFloatBuffer()
175 | .put(fArray);
176 | fBuffer.position(0);
177 | return fBuffer;
178 | }
179 |
180 | public static ShortBuffer arrayToShortBuffer(short[] sArray) {
181 | ShortBuffer sBuffer = ByteBuffer.allocateDirect(sArray.length * 2)
182 | .order(ByteOrder.nativeOrder())
183 | .asShortBuffer()
184 | .put(sArray);
185 | sBuffer.position(0);
186 | return sBuffer;
187 | }
188 |
189 | }
190 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/t_gl.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DMings/LearnOpengl/4f3c4d0974c29d8da6672a3acf4187e828f80a92/app/src/main/res/drawable-xxhdpi/t_gl.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/test_gl.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DMings/LearnOpengl/4f3c4d0974c29d8da6672a3acf4187e828f80a92/app/src/main/res/drawable-xxhdpi/test_gl.jpg
--------------------------------------------------------------------------------
/app/src/main/res/layout/act_test.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
12 |
13 |
18 |
19 |
23 |
24 |
25 |
29 |
30 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DMings/LearnOpengl/4f3c4d0974c29d8da6672a3acf4187e828f80a92/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/raw/animation_frg.glsl:
--------------------------------------------------------------------------------
1 | #extension GL_OES_EGL_image_external : require
2 | precision mediump float;
3 | varying vec2 textureCoordinate;
4 | uniform samplerExternalOES inputImageOESTexture;
5 | uniform int isVideo;
6 |
7 | void main() {
8 | vec4 color = texture2D(inputImageOESTexture, textureCoordinate);
9 | if (isVideo != 0){
10 | if (color.r < 0.1 && color.g < 0.1 && color.b < 0.1){
11 | color = vec4(0, 0, 0, 0);
12 | }
13 | }
14 | gl_FragColor = color;
15 | }
--------------------------------------------------------------------------------
/app/src/main/res/raw/blur_frg.glsl:
--------------------------------------------------------------------------------
1 | #extension GL_OES_EGL_image_external : require
2 | precision lowp float;
3 | varying vec2 textureCoordinate;// st xy
4 | uniform samplerExternalOES inputImageOESTexture;
5 | uniform int isVertical;
6 |
7 | void main() {
8 | vec2 tex_offset =vec2(1.0/300.0, 1.0/300.0);
9 | vec4 outColor = texture2D(inputImageOESTexture, textureCoordinate);
10 | float orAlpha=outColor.a;
11 | // float weight[] = float[] (0.227027, 0.1945946, 0.1216216, 0.054054, 0.016216);
12 | float weight[5];
13 | weight[0] = 0.227027;
14 | weight[1] = 0.1945946;
15 | weight[2] = 0.1216216;
16 | weight[3] = 0.054054;
17 | weight[4] = 0.016216;
18 | vec3 color=outColor.rgb*weight[0];
19 | if (isVertical != 0) {
20 | for (int i=1;i<5;i++) {
21 | color+=texture2D(inputImageOESTexture, textureCoordinate+vec2(tex_offset.x * float(i), 0.0)).rgb*weight[i];
22 | color+=texture2D(inputImageOESTexture, textureCoordinate-vec2(tex_offset.x * float(i), 0.0)).rgb*weight[i];
23 | }
24 | }
25 | else {
26 | for (int i=1;i<5;i++) {
27 | color+=texture2D(inputImageOESTexture, textureCoordinate+vec2(0.0, tex_offset.y * float(i))).rgb*weight[i];
28 | color+=texture2D(inputImageOESTexture, textureCoordinate-vec2(0.0, tex_offset.y * float(i))).rgb*weight[i];
29 | }
30 | }
31 | gl_FragColor=vec4(color, orAlpha);
32 | }
--------------------------------------------------------------------------------
/app/src/main/res/raw/burr_frg.glsl:
--------------------------------------------------------------------------------
1 | #extension GL_OES_EGL_image_external : require
2 | precision mediump float;
3 | //precision highp float;
4 | varying vec2 textureCoordinate;// st xy
5 | uniform samplerExternalOES inputImageOESTexture;
6 | uniform float inputTime;
7 |
8 | float rand(float n) {
9 | //fract(x),返回x的小数部分数据
10 | return fract(sin(n) * 43758.5453123);
11 | }
12 |
13 | void main (void) {
14 | // 最大抖动
15 | float maxJitter = 0.06;
16 | // 一次毛刺滤镜的时长
17 | float duration = 0.5;
18 | // 红色颜色偏移量
19 | float colorROffset = 0.01;
20 | //绿色颜色偏移量
21 | float colorGOffset = -0.02;
22 | // 蓝色颜色偏移量
23 | float colorBOffset = -0.035;
24 |
25 | // 时间周期[0.0,1.0];
26 | float time = mod(inputTime, duration * 2.0);
27 | // 振幅:[0,1];
28 | float amplitude = max(sin(time * (3.141592 / duration)), 0.0);
29 |
30 | // 像素随机偏移[-1,1]
31 | float jitter = rand(textureCoordinate.y) * 2.0 - 1.0; // -1~1
32 |
33 | // 是否要做偏移.
34 | bool needOffset = abs(jitter) < maxJitter * amplitude;
35 |
36 | // 获取纹理X值.根据needOffset,来计算它X撕裂.
37 | // needOffset = YES,撕裂较大;
38 | // needOffset = NO,撕裂较小.
39 | float textureX = textureCoordinate.x + (needOffset ? jitter : (jitter * amplitude * 0.006));
40 |
41 | // 撕裂后的纹理坐标x,y
42 | vec2 textureCoords = vec2(textureX, textureCoordinate.y);
43 |
44 | // 颜色偏移3组颜色
45 | // 根据撕裂后获取的纹理颜色值
46 | vec4 mask = texture2D(inputImageOESTexture, textureCoords);
47 | // 撕裂后的纹理颜色偏移
48 | vec4 maskR = texture2D(inputImageOESTexture, textureCoords + vec2(colorROffset * amplitude, 0.0));
49 | vec4 maskG = texture2D(inputImageOESTexture, textureCoords + vec2(colorGOffset * amplitude, 0.0));
50 | vec4 maskB = texture2D(inputImageOESTexture, textureCoords + vec2(colorBOffset * amplitude, 0.0));
51 |
52 | // 颜色部分发生撕裂.
53 | gl_FragColor = vec4(maskR.r, maskG.g, maskB.b, mask.a);
54 | }
--------------------------------------------------------------------------------
/app/src/main/res/raw/edge_frg.glsl:
--------------------------------------------------------------------------------
1 | //#version 120
2 | #extension GL_OES_EGL_image_external : require
3 | precision mediump float;
4 | varying vec2 textureCoordinate;
5 | uniform samplerExternalOES inputImageOESTexture;
6 | const float texelOffset = 1.0 / 300.0;
7 | const int coreSize = 3;
8 |
9 | void main()
10 | {
11 | vec4 color = vec4(0.0,0.0,0.0,1.0);
12 | float kernel[9];
13 | kernel[6] = 0.0; kernel[7] = -1.0; kernel[8] = 0.0;
14 | kernel[3] = -1.0; kernel[4] = 4.0; kernel[5] = -1.0;
15 | kernel[0] = 0.0; kernel[1] = -1.0; kernel[2] = 0.0;
16 |
17 | int index = 0;
18 | for (int y = 0; y
2 |
3 | #111111
4 | #000000
5 | #FFFFFF
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | NineGL
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/test/java/com/dming/testopengl/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.dming.testopengl;
2 |
3 | import org.junit.Test;
4 |
5 | import java.nio.ByteBuffer;
6 | import java.nio.ByteOrder;
7 | import java.nio.FloatBuffer;
8 |
9 | import static org.junit.Assert.*;
10 |
11 | /**
12 | * Example local unit test, which will execute on the development machine (host).
13 | *
14 | * @see Testing documentation
15 | */
16 | public class ExampleUnitTest {
17 |
18 | @Test
19 | public void addition_isCorrect() {
20 | // assertEquals(4, 2 + 2);
21 | float[] tempTex = {
22 | 0, 0.667f,
23 | 0, 0.334f,
24 | 1, 0.334f,
25 | 1, 0.667f,
26 | };
27 | FloatBuffer fBuffer = ByteBuffer.allocateDirect(tempTex.length * 4)
28 | .order(ByteOrder.nativeOrder())
29 | .asFloatBuffer()
30 | .put(tempTex);
31 | fBuffer.position(0);
32 | //
33 | System.out.println("fBuffer.capacity()>" + fBuffer.capacity());
34 | for (int i = 0; i < fBuffer.capacity(); i++) {
35 | System.out.println("fBuffer-" + i + " > " + fBuffer.get(i));
36 | }
37 | tempTex[3] = 88;
38 | tempTex[6] = 44;
39 | tempTex[7] = 99;
40 | // fBuffer.position(0);
41 | fBuffer.put(tempTex);
42 | for (int i = 0; i < fBuffer.capacity(); i++) {
43 | System.out.println("=-" + i + " > " + fBuffer.get(i));
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 |
5 | repositories {
6 | google()
7 | jcenter()
8 | }
9 | dependencies {
10 | classpath 'com.android.tools.build:gradle:3.5.1'
11 |
12 |
13 | // NOTE: Do not place your application dependencies here; they belong
14 | // in the individual module build.gradle files
15 | }
16 | }
17 |
18 | allprojects {
19 | repositories {
20 | google()
21 | jcenter()
22 | }
23 | }
24 |
25 | task clean(type: Delete) {
26 | delete rootProject.buildDir
27 | }
28 |
--------------------------------------------------------------------------------
/giflib/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/giflib/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 28
5 |
6 |
7 | defaultConfig {
8 | minSdkVersion 17
9 | targetSdkVersion 28
10 | versionCode 1
11 | versionName "1.0"
12 |
13 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
14 | externalNativeBuild {
15 | cmake {
16 | cppFlags ""
17 | }
18 | }
19 | }
20 |
21 | buildTypes {
22 | release {
23 | minifyEnabled false
24 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
25 | }
26 | }
27 | externalNativeBuild {
28 | cmake {
29 | path "src/main/cpp/CMakeLists.txt"
30 | // version "3.10.2"
31 | }
32 | }
33 | }
34 |
35 | dependencies {
36 | implementation fileTree(dir: 'libs', include: ['*.jar'])
37 |
38 | implementation 'com.android.support:appcompat-v7:28.0.0'
39 | testImplementation 'junit:junit:4.12'
40 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
41 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
42 | }
43 |
--------------------------------------------------------------------------------
/giflib/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/giflib/src/androidTest/java/com/dming/giflib/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.dming.giflib;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.dming.giflib.test", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/giflib/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/giflib/src/main/assets/mogutou.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DMings/LearnOpengl/4f3c4d0974c29d8da6672a3acf4187e828f80a92/giflib/src/main/assets/mogutou.gif
--------------------------------------------------------------------------------
/giflib/src/main/assets/mogutou2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DMings/LearnOpengl/4f3c4d0974c29d8da6672a3acf4187e828f80a92/giflib/src/main/assets/mogutou2.gif
--------------------------------------------------------------------------------
/giflib/src/main/cpp/CMakeLists.txt:
--------------------------------------------------------------------------------
1 |
2 | cmake_minimum_required(VERSION 3.4.1)
3 |
4 | file(GLOB_RECURSE GIF_DIRECTORIES ${CMAKE_SOURCE_DIR}/giflib/*.*)
5 |
6 | add_library(
7 | gifplayer
8 | SHARED
9 | PthreadSleep.cpp
10 | SyncTime.cpp
11 | GifPlayer.cpp
12 | GifJni.cpp
13 | GLUtils.cpp
14 | ${GIF_DIRECTORIES}
15 | # giflib/dgif_lib.c
16 | # giflib/egif_lib.c
17 | # giflib/gif_err.c
18 | # giflib/gif_hash.c
19 | # giflib/gifalloc.c
20 | # giflib/openbsd-reallocarray.c
21 | # giflib/quantize.c
22 | )
23 |
24 |
25 | target_link_libraries(
26 | gifplayer
27 | GLESv2
28 | log
29 | android)
--------------------------------------------------------------------------------
/giflib/src/main/cpp/GLUtils.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Administrator on 2019/9/11.
3 | //
4 |
5 | #include "GLUtils.h"
6 |
7 |
8 | GLuint GLUtils::createShader(GLenum shaderType, const char *src) {
9 | GLuint shader = glCreateShader(shaderType);
10 | if (!shader) {
11 | GLUtils::checkErr("glCreateShader");
12 | return 0;
13 | }
14 | glShaderSource(shader, 1, &src, NULL);
15 |
16 | GLint compiled = GL_FALSE;
17 | glCompileShader(shader);
18 | glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
19 | if (!compiled) {
20 | GLint infoLogLen = 0;
21 | glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLen);
22 | if (infoLogLen > 0) {
23 | GLchar *infoLog = (GLchar *) malloc((size_t)infoLogLen);
24 | if (infoLog) {
25 | glGetShaderInfoLog(shader, infoLogLen, NULL, infoLog);
26 | LOGE("Could not compile %s shader:\n%s\n",
27 | shaderType == GL_VERTEX_SHADER ? "vertex" : "fragment",
28 | infoLog);
29 | free(infoLog);
30 | }
31 | }
32 | glDeleteShader(shader);
33 | return 0;
34 | }
35 | return shader;
36 | }
37 |
38 | GLuint GLUtils::createProgram(const char *vtxSrc, const char *fragSrc) {
39 | GLuint vtxShader = 0;
40 | GLuint fragShader = 0;
41 | GLuint program = 0;
42 | GLint linked = GL_FALSE;
43 |
44 | vtxShader = createShader(GL_VERTEX_SHADER, vtxSrc);
45 | if (!vtxShader)
46 | goto exit;
47 |
48 | fragShader = createShader(GL_FRAGMENT_SHADER, fragSrc);
49 | if (!fragShader)
50 | goto exit;
51 |
52 | program = glCreateProgram();
53 | if (!program) {
54 | GLUtils::checkErr("glCreateProgram");
55 | goto exit;
56 | }
57 | glAttachShader(program, vtxShader);
58 | glAttachShader(program, fragShader);
59 |
60 | glLinkProgram(program);
61 | glGetProgramiv(program, GL_LINK_STATUS, &linked);
62 | if (!linked) {
63 | LOGE("Could not link program");
64 | GLint infoLogLen = 0;
65 | glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLen);
66 | if (infoLogLen) {
67 | GLchar *infoLog = (GLchar *) malloc((size_t)infoLogLen);
68 | if (infoLog) {
69 | glGetProgramInfoLog(program, infoLogLen, NULL, infoLog);
70 | LOGE("Could not link program: %s", infoLog);
71 | free(infoLog);
72 | }
73 | }
74 | glDeleteProgram(program);
75 | program = 0;
76 | }
77 | exit:
78 | glDeleteShader(vtxShader);
79 | glDeleteShader(fragShader);
80 | return program;
81 | }
82 |
83 |
84 | void GLUtils::checkErr() {
85 | GLenum err = glGetError();
86 | if (err != GL_NO_ERROR) {
87 | LOGE("gl get Error: %d", err);
88 | }
89 | }
90 |
91 | void GLUtils::checkErr(const char *tagName) {
92 | GLenum err = glGetError();
93 | if (err != GL_NO_ERROR) {
94 | LOGE("gl %s get Error: %d", tagName,err);
95 | }
96 | }
--------------------------------------------------------------------------------
/giflib/src/main/cpp/GLUtils.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Administrator on 2019/9/11.
3 | //
4 |
5 | #ifndef TESTPLAYER_GLUTILS_H
6 | #define TESTPLAYER_GLUTILS_H
7 |
8 | #include
9 | #include "log.h"
10 | #include
11 |
12 | class GLUtils {
13 | public:
14 | static GLuint createShader(GLenum shaderType, const char *src);
15 | static GLuint createProgram(const char *vtxSrc, const char *fragSrc);
16 | static void checkErr();
17 | static void checkErr(const char *tagName);
18 | private:
19 | };
20 |
21 |
22 | #endif //TESTPLAYER_GLUTILS_H
23 |
--------------------------------------------------------------------------------
/giflib/src/main/cpp/GifJni.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Administrator on 2019/9/30.
3 | //
4 | #include
5 | #include "GifPlayer.h"
6 |
7 | JNIEXPORT jlong JNICALL
8 | create_jni(JNIEnv *env, jobject instance) {
9 | GifPlayer *gifPlayer = new GifPlayer();
10 | jlong gifPtr = (jlong) gifPlayer;
11 | return gifPtr;
12 | }
13 |
14 | JNIEXPORT jboolean JNICALL
15 | load_jni(JNIEnv *env, jobject instance, jlong gifPlayerFormJava,
16 | jobject assetManager, jstring gifPath_) {
17 | const char *gifPath = env->GetStringUTFChars(gifPath_, 0);
18 | GifPlayer *gifPlayer = (GifPlayer *) gifPlayerFormJava;
19 | jboolean ret;
20 | if (gifPlayer) {
21 | ret = gifPlayer->load_gif(env, assetManager, gifPath);
22 | } else {
23 | ret = JNI_FALSE;
24 | }
25 | env->ReleaseStringUTFChars(gifPath_, gifPath);
26 | return ret;
27 | }
28 |
29 | JNIEXPORT void JNICALL
30 | start_jni(JNIEnv *env, jobject instance, jlong gifPlayerFormJava, jboolean once, jint texture,
31 | jobject runnable) {
32 | GifPlayer *gifPlayer = (GifPlayer *) gifPlayerFormJava;
33 | if (gifPlayer) {
34 | gifPlayer->start(env, once, texture, runnable);
35 | }
36 | }
37 |
38 | JNIEXPORT void JNICALL pause_jni(JNIEnv *env, jobject instance, jlong gifPlayerFormJava) {
39 | GifPlayer *gifPlayer = (GifPlayer *) gifPlayerFormJava;
40 | if (gifPlayer) {
41 | gifPlayer->pause();
42 | }
43 | }
44 |
45 | JNIEXPORT void JNICALL resume_jni(JNIEnv *env, jobject instance, jlong gifPlayerFormJava) {
46 | GifPlayer *gifPlayer = (GifPlayer *) gifPlayerFormJava;
47 | if (gifPlayer) {
48 | gifPlayer->resume();
49 | }
50 | }
51 |
52 | JNIEXPORT jint JNICALL get_width_jni(JNIEnv *env, jobject instance, jlong gifPlayerFormJava) {
53 | GifPlayer *gifPlayer = (GifPlayer *) gifPlayerFormJava;
54 | if (gifPlayer) {
55 | return gifPlayer->get_width();
56 | } else {
57 | return 0;
58 | }
59 | }
60 |
61 | JNIEXPORT jint JNICALL get_height_jni(JNIEnv *env, jobject instance, jlong gifPlayerFormJava) {
62 | GifPlayer *gifPlayer = (GifPlayer *) gifPlayerFormJava;
63 | if (gifPlayer) {
64 | return gifPlayer->get_height();
65 | } else {
66 | return 0;
67 | }
68 | }
69 |
70 | JNIEXPORT void JNICALL stop_jni(JNIEnv *env, jobject instance, jlong gifPlayerFormJava) {
71 | GifPlayer *gifPlayer = (GifPlayer *) gifPlayerFormJava;
72 | if (gifPlayer) {
73 | gifPlayer->release();
74 | }
75 | }
76 |
77 | JNIEXPORT void JNICALL release_jni(JNIEnv *env, jobject instance, jlong gifPlayerFormJava) {
78 | GifPlayer *gifPlayer = (GifPlayer *) gifPlayerFormJava;
79 | if (gifPlayer) {
80 | delete (gifPlayer);
81 | }
82 | }
83 |
84 | JNINativeMethod method[] = {
85 | {"native_create", "()J", (void *) create_jni},
86 | {"native_load", "(JLandroid/content/res/AssetManager;Ljava/lang/String;)Z", (void *) load_jni},
87 | {"native_start", "(JZILjava/lang/Runnable;)V", (void *) start_jni},
88 | {"native_pause", "(J)V", (void *) pause_jni},
89 | {"native_resume", "(J)V", (void *) resume_jni},
90 | {"native_get_width", "(J)I", (void *) get_width_jni},
91 | {"native_get_height", "(J)I", (void *) get_height_jni},
92 | {"native_stop", "(J)V", (void *) stop_jni},
93 | {"native_release", "(J)V", (void *) release_jni},
94 | };
95 |
96 | jint registerNativeMethod(JNIEnv *env) {
97 | jclass cl = env->FindClass("com/dming/testgif/GifPlayer");
98 | if ((env->RegisterNatives(cl, method, sizeof(method) / sizeof(method[0]))) < 0) {
99 | return -1;
100 | }
101 | return 0;
102 | }
103 |
104 | jint unRegisterNativeMethod(JNIEnv *env) {
105 | jclass cl = env->FindClass("com/dming/testgif/GifPlayer");
106 | env->UnregisterNatives(cl);
107 | return 0;
108 | }
109 |
110 | JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
111 | JNIEnv *env;
112 | if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) == JNI_OK) {
113 | registerNativeMethod(env);
114 | return JNI_VERSION_1_6;
115 | } else if (vm->GetEnv((void **) &env, JNI_VERSION_1_4) == JNI_OK) {
116 | registerNativeMethod(env);
117 | return JNI_VERSION_1_4;
118 | }
119 | return JNI_ERR;
120 | }
121 |
122 | JNIEXPORT void JNI_OnUnload(JavaVM *vm, void *reserved) {
123 | JNIEnv *env;
124 | if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) == JNI_OK) {
125 | unRegisterNativeMethod(env);
126 | } else if (vm->GetEnv((void **) &env, JNI_VERSION_1_4) == JNI_OK) {
127 | unRegisterNativeMethod(env);
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/giflib/src/main/cpp/GifPlayer.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Administrator on 2019/9/30.
3 | //
4 |
5 | #ifndef TESTGIF_GIFJNI_H
6 | #define TESTGIF_GIFJNI_H
7 |
8 | #include
9 | #include "giflib/gif_lib.h"
10 | #include "PthreadSleep.h"
11 | #include "SyncTime.h"
12 |
13 | #define UNSIGNED_LITTLE_ENDIAN(lo, hi) ((lo) | ((hi) << 8))
14 | #define MAKE_COLOR_ABGR(r, g, b) ((0xff) << 24 ) | ((b) << 16 ) | ((g) << 8 ) | ((r) & 0xff)
15 |
16 | enum PlayState {
17 | IDLE, PREPARE, PLAYING
18 | };
19 |
20 | class GifPlayer {
21 | public:
22 | jboolean load_gif(JNIEnv *env, jobject assetManager, const char *gifPath);
23 |
24 | void start(JNIEnv *env, jboolean once, jint texture, jobject runnable);
25 |
26 | void pause();
27 |
28 | void resume();
29 |
30 | jint get_width();
31 |
32 | jint get_height();
33 |
34 | void release();
35 |
36 | private:
37 | GifFileType *gifFile = NULL;
38 | PthreadSleep threadSleep;
39 | SyncTime syncTime;
40 | pthread_mutex_t play_mutex = PTHREAD_MUTEX_INITIALIZER;
41 | pthread_cond_t play_cond = PTHREAD_COND_INITIALIZER;
42 | bool is_pause = false;
43 | bool is_play_quit = false;
44 | int gif_width = 0;
45 | int gif_height = 0;
46 | int transparentColorIndex = 0;
47 | int bgColorIndex;
48 | int disposalMode = DISPOSAL_UNSPECIFIED;
49 | enum PlayState play_state = IDLE;
50 |
51 | void setPlayState(PlayState state);
52 |
53 | void getPlayState(PlayState *playState);
54 |
55 | void PrintGifError(int Error);
56 |
57 | int prepareGif(JNIEnv *env, jobject assetManager, const char *filename);
58 |
59 | uint32_t gifColorToColorARGB(const GifColorType &color);
60 |
61 | void setColorARGB(uint32_t *sPixels, int imageIndex, ColorMapObject *colorMap,
62 | GifByteType colorIndex);
63 |
64 | void playGif(JNIEnv *env, bool once, uint texture, jobject runnable);
65 |
66 | void drawGL(uint texture, uint32_t *pixels, int imageIndex,
67 | SavedImage *SavedImages, ColorMapObject *ColorMap,
68 | GifRowType *ScreenBuffer,
69 | int left, int top,
70 | int width, int height);
71 | };
72 |
73 | #endif //TESTGIF_GIFJNI_H
74 |
--------------------------------------------------------------------------------
/giflib/src/main/cpp/PthreadSleep.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Administrator on 2019/9/29.
3 | //
4 |
5 | #include "PthreadSleep.h"
6 |
7 | PthreadSleep::PthreadSleep() : is_interrupt(false) {
8 | pthread_mutex_init(&sleep_mutex, NULL);
9 | pthread_cond_init(&sleep_cond, NULL);
10 | }
11 |
12 | PthreadSleep::~PthreadSleep() {
13 | pthread_mutex_destroy(&sleep_mutex);
14 | pthread_cond_destroy(&sleep_cond);
15 | }
16 |
17 |
18 | void PthreadSleep::msleep(unsigned int ms) {
19 | struct timespec deadline;
20 | struct timeval now;
21 |
22 | gettimeofday(&now, NULL);
23 | time_t seconds = (time_t) (ms / 1000);
24 | long nanoseconds = (long) ((ms - seconds * 1000) * 1000000);
25 |
26 | deadline.tv_sec = now.tv_sec + seconds;
27 | deadline.tv_nsec = now.tv_usec * 1000 + nanoseconds;
28 |
29 | if (deadline.tv_nsec >= 1000000000L) {
30 | deadline.tv_nsec -= 1000000000L;
31 | deadline.tv_sec++;
32 | }
33 | pthread_mutex_lock(&sleep_mutex);
34 | if (!is_interrupt) {
35 | pthread_cond_timedwait(&sleep_cond, &sleep_mutex, &deadline);
36 | }
37 | pthread_mutex_unlock(&sleep_mutex);
38 | }
39 |
40 | void PthreadSleep::reset() {
41 | pthread_mutex_lock(&sleep_mutex);
42 | is_interrupt = false;
43 | pthread_mutex_unlock(&sleep_mutex);
44 | }
45 |
46 | void PthreadSleep::interrupt() {
47 | pthread_mutex_lock(&sleep_mutex);
48 | is_interrupt = true;
49 | pthread_cond_signal(&sleep_cond);
50 | pthread_mutex_unlock(&sleep_mutex);
51 | }
--------------------------------------------------------------------------------
/giflib/src/main/cpp/PthreadSleep.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Administrator on 2019/9/29.
3 | //
4 |
5 | #ifndef TESTGIF_PTHREADSLEEP_H
6 | #define TESTGIF_PTHREADSLEEP_H
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 |
13 | class PthreadSleep {
14 | public:
15 | PthreadSleep();
16 |
17 | ~PthreadSleep();
18 |
19 | void msleep(unsigned int ms);
20 |
21 | void reset();
22 |
23 | void interrupt();
24 |
25 | private:
26 | pthread_mutex_t sleep_mutex;
27 | pthread_cond_t sleep_cond;
28 | bool is_interrupt;
29 | };
30 |
31 | #endif //TESTGIF_PTHREADSLEEP_H
32 |
--------------------------------------------------------------------------------
/giflib/src/main/cpp/SyncTime.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Administrator on 2019/9/29.
3 | //
4 |
5 | #include "SyncTime.h"
6 |
7 | void SyncTime::set_clock() {
8 | clock_gettime(CLOCK_MONOTONIC, ¤t_ts);
9 | last_ts.tv_sec = current_ts.tv_sec;
10 | last_ts.tv_nsec = current_ts.tv_nsec;
11 | }
12 |
13 | unsigned int SyncTime::synchronize_time(int m_time) {
14 | unsigned int c_m_time;
15 | int diff_time;
16 | clock_gettime(CLOCK_MONOTONIC, ¤t_ts);
17 | c_m_time = (unsigned int) (1000 * (current_ts.tv_sec - last_ts.tv_sec) +
18 | (current_ts.tv_nsec - last_ts.tv_nsec) / 1000000);
19 | diff_time = m_time - c_m_time;
20 | // LOGI("synchronize_time c_m_time: %d m_time: %d diff_time:%d", c_m_time, m_time, diff_time);
21 | // return m_time;
22 | if (diff_time > 0) {
23 | return (unsigned int) diff_time;
24 | } else {
25 | return 0;
26 | }
27 | }
--------------------------------------------------------------------------------
/giflib/src/main/cpp/SyncTime.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Administrator on 2019/9/29.
3 | //
4 |
5 | #ifndef TESTGIF_SYNCTIME_H
6 | #define TESTGIF_SYNCTIME_H
7 |
8 | #include
9 | #include "log.h"
10 |
11 | class SyncTime {
12 |
13 | public:
14 |
15 | void set_clock();
16 |
17 | unsigned int synchronize_time(int m_time);
18 |
19 | private:
20 | timespec current_ts;
21 | timespec last_ts;
22 | };
23 |
24 | #endif //TESTGIF_SYNCTIME_H
25 |
--------------------------------------------------------------------------------
/giflib/src/main/cpp/giflib/config.h:
--------------------------------------------------------------------------------
1 |
2 | // giflib config.h
3 |
4 | #ifndef GIF_CONFIG_H_DEFINED
5 | #define GIF_CONFIG_H_DEFINED
6 |
7 | #include
8 | #include
9 | #include
10 |
11 | typedef uint32_t UINT32;
12 |
13 | #endif
14 |
--------------------------------------------------------------------------------
/giflib/src/main/cpp/giflib/gif_err.c:
--------------------------------------------------------------------------------
1 | /*****************************************************************************
2 |
3 | gif_err.c - handle error reporting for the GIF library.
4 |
5 | ****************************************************************************/
6 |
7 | #include
8 |
9 | #include "gif_lib.h"
10 | #include "gif_lib_private.h"
11 |
12 | /*****************************************************************************
13 | Return a string description of the last GIF error
14 | *****************************************************************************/
15 | const char *
16 | GifErrorString(int ErrorCode)
17 | {
18 | const char *Err;
19 |
20 | switch (ErrorCode) {
21 | case E_GIF_ERR_OPEN_FAILED:
22 | Err = "Failed to open given file";
23 | break;
24 | case E_GIF_ERR_WRITE_FAILED:
25 | Err = "Failed to write to given file";
26 | break;
27 | case E_GIF_ERR_HAS_SCRN_DSCR:
28 | Err = "Screen descriptor has already been set";
29 | break;
30 | case E_GIF_ERR_HAS_IMAG_DSCR:
31 | Err = "Image descriptor is still active";
32 | break;
33 | case E_GIF_ERR_NO_COLOR_MAP:
34 | Err = "Neither global nor local color map";
35 | break;
36 | case E_GIF_ERR_DATA_TOO_BIG:
37 | Err = "Number of pixels bigger than width * height";
38 | break;
39 | case E_GIF_ERR_NOT_ENOUGH_MEM:
40 | Err = "Failed to allocate required memory";
41 | break;
42 | case E_GIF_ERR_DISK_IS_FULL:
43 | Err = "Write failed (disk full?)";
44 | break;
45 | case E_GIF_ERR_CLOSE_FAILED:
46 | Err = "Failed to close given file";
47 | break;
48 | case E_GIF_ERR_NOT_WRITEABLE:
49 | Err = "Given file was not opened for write";
50 | break;
51 | case D_GIF_ERR_OPEN_FAILED:
52 | Err = "Failed to open given file";
53 | break;
54 | case D_GIF_ERR_READ_FAILED:
55 | Err = "Failed to read from given file";
56 | break;
57 | case D_GIF_ERR_NOT_GIF_FILE:
58 | Err = "Data is not in GIF format";
59 | break;
60 | case D_GIF_ERR_NO_SCRN_DSCR:
61 | Err = "No screen descriptor detected";
62 | break;
63 | case D_GIF_ERR_NO_IMAG_DSCR:
64 | Err = "No Image Descriptor detected";
65 | break;
66 | case D_GIF_ERR_NO_COLOR_MAP:
67 | Err = "Neither global nor local color map";
68 | break;
69 | case D_GIF_ERR_WRONG_RECORD:
70 | Err = "Wrong record type detected";
71 | break;
72 | case D_GIF_ERR_DATA_TOO_BIG:
73 | Err = "Number of pixels bigger than width * height";
74 | break;
75 | case D_GIF_ERR_NOT_ENOUGH_MEM:
76 | Err = "Failed to allocate required memory";
77 | break;
78 | case D_GIF_ERR_CLOSE_FAILED:
79 | Err = "Failed to close given file";
80 | break;
81 | case D_GIF_ERR_NOT_READABLE:
82 | Err = "Given file was not opened for read";
83 | break;
84 | case D_GIF_ERR_IMAGE_DEFECT:
85 | Err = "Image is defective, decoding aborted";
86 | break;
87 | case D_GIF_ERR_EOF_TOO_SOON:
88 | Err = "Image EOF detected before image complete";
89 | break;
90 | default:
91 | Err = NULL;
92 | break;
93 | }
94 | return Err;
95 | }
96 |
97 | /* end */
98 |
--------------------------------------------------------------------------------
/giflib/src/main/cpp/giflib/gif_font.c:
--------------------------------------------------------------------------------
1 | /*****************************************************************************
2 |
3 | gif_font.c - utility font handling and simple drawing for the GIF library
4 |
5 | ****************************************************************************/
6 |
7 | #include
8 | #include
9 |
10 | #include "gif_lib.h"
11 |
12 | /*****************************************************************************
13 | Ascii 8 by 8 regular font - only first 128 characters are supported.
14 | *****************************************************************************/
15 |
16 | /*
17 | * Each array entry holds the bits for 8 horizontal scan lines, topmost
18 | * first. The most significant bit of each constant is the leftmost bit of
19 | * the scan line.
20 | */
21 | /*@+charint@*/
22 | const unsigned char GifAsciiTable8x8[][GIF_FONT_WIDTH] = {
23 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* Ascii 0 */
24 | {0x3c, 0x42, 0xa5, 0x81, 0xbd, 0x42, 0x3c, 0x00}, /* Ascii 1 */
25 | {0x3c, 0x7e, 0xdb, 0xff, 0xc3, 0x7e, 0x3c, 0x00}, /* Ascii 2 */
26 | {0x00, 0xee, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00}, /* Ascii 3 */
27 | {0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00}, /* Ascii 4 */
28 | {0x00, 0x3c, 0x18, 0xff, 0xff, 0x08, 0x18, 0x00}, /* Ascii 5 */
29 | {0x10, 0x38, 0x7c, 0xfe, 0xfe, 0x10, 0x38, 0x00}, /* Ascii 6 */
30 | {0x00, 0x00, 0x18, 0x3c, 0x18, 0x00, 0x00, 0x00}, /* Ascii 7 */
31 | {0xff, 0xff, 0xe7, 0xc3, 0xe7, 0xff, 0xff, 0xff}, /* Ascii 8 */
32 | {0x00, 0x3c, 0x42, 0x81, 0x81, 0x42, 0x3c, 0x00}, /* Ascii 9 */
33 | {0xff, 0xc3, 0xbd, 0x7e, 0x7e, 0xbd, 0xc3, 0xff}, /* Ascii 10 */
34 | {0x1f, 0x07, 0x0d, 0x7c, 0xc6, 0xc6, 0x7c, 0x00}, /* Ascii 11 */
35 | {0x00, 0x7e, 0xc3, 0xc3, 0x7e, 0x18, 0x7e, 0x18}, /* Ascii 12 */
36 | {0x04, 0x06, 0x07, 0x04, 0x04, 0xfc, 0xf8, 0x00}, /* Ascii 13 */
37 | {0x0c, 0x0a, 0x0d, 0x0b, 0xf9, 0xf9, 0x1f, 0x1f}, /* Ascii 14 */
38 | {0x00, 0x92, 0x7c, 0x44, 0xc6, 0x7c, 0x92, 0x00}, /* Ascii 15 */
39 | {0x00, 0x00, 0x60, 0x78, 0x7e, 0x78, 0x60, 0x00}, /* Ascii 16 */
40 | {0x00, 0x00, 0x06, 0x1e, 0x7e, 0x1e, 0x06, 0x00}, /* Ascii 17 */
41 | {0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x18}, /* Ascii 18 */
42 | {0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00}, /* Ascii 19 */
43 | {0xff, 0xb6, 0x76, 0x36, 0x36, 0x36, 0x36, 0x00}, /* Ascii 20 */
44 | {0x7e, 0xc1, 0xdc, 0x22, 0x22, 0x1f, 0x83, 0x7e}, /* Ascii 21 */
45 | {0x00, 0x00, 0x00, 0x7e, 0x7e, 0x00, 0x00, 0x00}, /* Ascii 22 */
46 | {0x18, 0x7e, 0x18, 0x18, 0x7e, 0x18, 0x00, 0xff}, /* Ascii 23 */
47 | {0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00}, /* Ascii 24 */
48 | {0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x00}, /* Ascii 25 */
49 | {0x00, 0x04, 0x06, 0xff, 0x06, 0x04, 0x00, 0x00}, /* Ascii 26 */
50 | {0x00, 0x20, 0x60, 0xff, 0x60, 0x20, 0x00, 0x00}, /* Ascii 27 */
51 | {0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0x00}, /* Ascii 28 */
52 | {0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00}, /* Ascii 29 */
53 | {0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x00, 0x00}, /* Ascii 30 */
54 | {0x00, 0x00, 0x00, 0xfe, 0x7c, 0x38, 0x10, 0x00}, /* Ascii 31 */
55 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* */
56 | {0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x30, 0x00}, /* ! */
57 | {0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* " */
58 | {0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00}, /* # */
59 | {0x10, 0x7c, 0xd2, 0x7c, 0x86, 0x7c, 0x10, 0x00}, /* $ */
60 | {0xf0, 0x96, 0xfc, 0x18, 0x3e, 0x72, 0xde, 0x00}, /* % */
61 | {0x30, 0x48, 0x30, 0x78, 0xce, 0xcc, 0x78, 0x00}, /* & */
62 | {0x0c, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00}, /* ' */
63 | {0x10, 0x60, 0xc0, 0xc0, 0xc0, 0x60, 0x10, 0x00}, /* ( */
64 | {0x10, 0x0c, 0x06, 0x06, 0x06, 0x0c, 0x10, 0x00}, /* ) */
65 | {0x00, 0x54, 0x38, 0xfe, 0x38, 0x54, 0x00, 0x00}, /* * */
66 | {0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00}, /* + */
67 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x70}, /* , */
68 | {0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00}, /* - */
69 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00}, /* . */
70 | {0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x00}, /* / */
71 | {0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00}, /* 0 */
72 | {0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x3c, 0x00}, /* 1 */
73 | {0x7c, 0xc6, 0x06, 0x0c, 0x30, 0x60, 0xfe, 0x00}, /* 2 */
74 | {0x7c, 0xc6, 0x06, 0x3c, 0x06, 0xc6, 0x7c, 0x00}, /* 3 */
75 | {0x0e, 0x1e, 0x36, 0x66, 0xfe, 0x06, 0x06, 0x00}, /* 4 */
76 | {0xfe, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0xfc, 0x00}, /* 5 */
77 | {0x7c, 0xc6, 0xc0, 0xfc, 0xc6, 0xc6, 0x7c, 0x00}, /* 6 */
78 | {0xfe, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x60, 0x00}, /* 7 */
79 | {0x7c, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0x7c, 0x00}, /* 8 */
80 | {0x7c, 0xc6, 0xc6, 0x7e, 0x06, 0xc6, 0x7c, 0x00}, /* 9 */
81 | {0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00}, /* : */
82 | {0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x20, 0x00}, /* }, */
83 | {0x00, 0x1c, 0x30, 0x60, 0x30, 0x1c, 0x00, 0x00}, /* < */
84 | {0x00, 0x00, 0x7e, 0x00, 0x7e, 0x00, 0x00, 0x00}, /* = */
85 | {0x00, 0x70, 0x18, 0x0c, 0x18, 0x70, 0x00, 0x00}, /* > */
86 | {0x7c, 0xc6, 0x0c, 0x18, 0x30, 0x00, 0x30, 0x00}, /* ? */
87 | {0x7c, 0x82, 0x9a, 0xaa, 0xaa, 0x9e, 0x7c, 0x00}, /* @ */
88 | {0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00}, /* A */
89 | {0xfc, 0xc6, 0xc6, 0xfc, 0xc6, 0xc6, 0xfc, 0x00}, /* B */
90 | {0x7c, 0xc6, 0xc6, 0xc0, 0xc0, 0xc6, 0x7c, 0x00}, /* C */
91 | {0xf8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, 0xf8, 0x00}, /* D */
92 | {0xfe, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xfe, 0x00}, /* E */
93 | {0xfe, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0x00}, /* F */
94 | {0x7c, 0xc6, 0xc0, 0xce, 0xc6, 0xc6, 0x7e, 0x00}, /* G */
95 | {0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00}, /* H */
96 | {0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00}, /* I */
97 | {0x1e, 0x06, 0x06, 0x06, 0xc6, 0xc6, 0x7c, 0x00}, /* J */
98 | {0xc6, 0xcc, 0xd8, 0xf0, 0xd8, 0xcc, 0xc6, 0x00}, /* K */
99 | {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x00}, /* L */
100 | {0xc6, 0xee, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0x00}, /* M */
101 | {0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00}, /* N */
102 | {0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00}, /* O */
103 | {0xfc, 0xc6, 0xc6, 0xfc, 0xc0, 0xc0, 0xc0, 0x00}, /* P */
104 | {0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x06}, /* Q */
105 | {0xfc, 0xc6, 0xc6, 0xfc, 0xc6, 0xc6, 0xc6, 0x00}, /* R */
106 | {0x78, 0xcc, 0x60, 0x30, 0x18, 0xcc, 0x78, 0x00}, /* S */
107 | {0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00}, /* T */
108 | {0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00}, /* U */
109 | {0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00}, /* V */
110 | {0xc6, 0xc6, 0xc6, 0xd6, 0xfe, 0xee, 0xc6, 0x00}, /* W */
111 | {0xc6, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0xc6, 0x00}, /* X */
112 | {0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x00}, /* Y */
113 | {0xfe, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xfe, 0x00}, /* Z */
114 | {0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00}, /* [ */
115 | {0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x00}, /* \ */
116 | {0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00}, /* ] */
117 | {0x00, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00}, /* ^ */
118 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff}, /* _ */
119 | {0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00}, /* ` */
120 | {0x00, 0x00, 0x7c, 0x06, 0x7e, 0xc6, 0x7e, 0x00}, /* a */
121 | {0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xe6, 0xdc, 0x00}, /* b */
122 | {0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0x7e, 0x00}, /* c */
123 | {0x06, 0x06, 0x7e, 0xc6, 0xc6, 0xce, 0x76, 0x00}, /* d */
124 | {0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0x7e, 0x00}, /* e */
125 | {0x1e, 0x30, 0x7c, 0x30, 0x30, 0x30, 0x30, 0x00}, /* f */
126 | {0x00, 0x00, 0x7e, 0xc6, 0xce, 0x76, 0x06, 0x7c}, /* g */
127 | {0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x00}, /* */
128 | {0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00}, /* i */
129 | {0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0xf0}, /* j */
130 | {0xc0, 0xc0, 0xcc, 0xd8, 0xf0, 0xd8, 0xcc, 0x00}, /* k */
131 | {0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00}, /* l */
132 | {0x00, 0x00, 0xcc, 0xfe, 0xd6, 0xc6, 0xc6, 0x00}, /* m */
133 | {0x00, 0x00, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x00}, /* n */
134 | {0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00}, /* o */
135 | {0x00, 0x00, 0xfc, 0xc6, 0xc6, 0xe6, 0xdc, 0xc0}, /* p */
136 | {0x00, 0x00, 0x7e, 0xc6, 0xc6, 0xce, 0x76, 0x06}, /* q */
137 | {0x00, 0x00, 0x6e, 0x70, 0x60, 0x60, 0x60, 0x00}, /* r */
138 | {0x00, 0x00, 0x7c, 0xc0, 0x7c, 0x06, 0xfc, 0x00}, /* s */
139 | {0x30, 0x30, 0x7c, 0x30, 0x30, 0x30, 0x1c, 0x00}, /* t */
140 | {0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x00}, /* u */
141 | {0x00, 0x00, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00}, /* v */
142 | {0x00, 0x00, 0xc6, 0xc6, 0xd6, 0xfe, 0x6c, 0x00}, /* w */
143 | {0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00}, /* x */
144 | {0x00, 0x00, 0xc6, 0xc6, 0xce, 0x76, 0x06, 0x7c}, /* y */
145 | {0x00, 0x00, 0xfc, 0x18, 0x30, 0x60, 0xfc, 0x00}, /* z */
146 | {0x0e, 0x18, 0x18, 0x70, 0x18, 0x18, 0x0e, 0x00}, /* { */
147 | {0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00}, /* | */
148 | {0xe0, 0x30, 0x30, 0x1c, 0x30, 0x30, 0xe0, 0x00}, /* } */
149 | {0x00, 0x00, 0x70, 0x9a, 0x0e, 0x00, 0x00, 0x00}, /* ~ */
150 | {0x00, 0x00, 0x18, 0x3c, 0x66, 0xff, 0x00, 0x00} /* Ascii 127 */
151 | };
152 | /*@=charint@*/
153 |
154 | void
155 | GifDrawText8x8(SavedImage *Image,
156 | const int x, const int y,
157 | const char *legend,
158 | const int color)
159 | {
160 | int i, j;
161 | int base;
162 | const char *cp;
163 |
164 | for (i = 0; i < GIF_FONT_HEIGHT; i++) {
165 | base = Image->ImageDesc.Width * (y + i) + x;
166 |
167 | for (cp = legend; *cp; cp++)
168 | for (j = 0; j < GIF_FONT_WIDTH; j++) {
169 | if (GifAsciiTable8x8[(short)(*cp)][i] & (1 << (GIF_FONT_WIDTH - j)))
170 | Image->RasterBits[base] = color;
171 | base++;
172 | }
173 | }
174 | }
175 |
176 | void
177 | GifDrawBox(SavedImage *Image,
178 | const int x, const int y,
179 | const int w, const int d,
180 | const int color)
181 | {
182 | int j, base = Image->ImageDesc.Width * y + x;
183 |
184 | for (j = 0; j < w; j++)
185 | Image->RasterBits[base + j] =
186 | Image->RasterBits[base + (d * Image->ImageDesc.Width) + j] = color;
187 |
188 | for (j = 0; j < d; j++)
189 | Image->RasterBits[base + j * Image->ImageDesc.Width] =
190 | Image->RasterBits[base + j * Image->ImageDesc.Width + w] = color;
191 | }
192 |
193 | void
194 | GifDrawRectangle(SavedImage *Image,
195 | const int x, const int y,
196 | const int w, const int d,
197 | const int color)
198 | {
199 | unsigned char *bp = Image->RasterBits + Image->ImageDesc.Width * y + x;
200 | int i;
201 |
202 | for (i = 0; i < d; i++)
203 | memset(bp + (i * Image->ImageDesc.Width), color, (size_t)w);
204 | }
205 |
206 | void
207 | GifDrawBoxedText8x8(SavedImage *Image,
208 | const int x, const int y,
209 | const char *legend,
210 | const int border,
211 | const int bg, const int fg)
212 | {
213 | int j = 0, LineCount = 0, TextWidth = 0;
214 | const char *cp;
215 | char *dup;
216 |
217 | /* compute size of text to box */
218 | for (cp = legend; *cp; cp++)
219 | if (*cp == '\r') {
220 | if (j > TextWidth)
221 | TextWidth = j;
222 | j = 0;
223 | LineCount++;
224 | } else if (*cp != '\t')
225 | ++j;
226 | LineCount++; /* count last line */
227 | if (j > TextWidth) /* last line might be longer than any previous */
228 | TextWidth = j;
229 |
230 | /* draw the text */
231 | dup = malloc(strlen(legend)+1);
232 | /* FIXME: should return bad status, but that would require API change */
233 | if (dup != NULL) {
234 | int i = 0;
235 | /* fill the box */
236 | GifDrawRectangle(Image, x + 1, y + 1,
237 | border + TextWidth * GIF_FONT_WIDTH + border - 1,
238 | border + LineCount * GIF_FONT_HEIGHT + border - 1, bg);
239 | (void)strcpy(dup, (char *)legend);
240 | cp = strtok((char *)dup, "\r\n");
241 | do {
242 | int leadspace = 0;
243 |
244 | if (cp[0] == '\t')
245 | leadspace = (TextWidth - strlen(++cp)) / 2;
246 |
247 | GifDrawText8x8(Image, x + border + (leadspace * GIF_FONT_WIDTH),
248 | y + border + (GIF_FONT_HEIGHT * i++), cp, fg);
249 | cp = strtok((char *)NULL, "\r\n");
250 | } while (cp);
251 | (void)free((void *)dup);
252 |
253 | /* outline the box */
254 | GifDrawBox(Image, x, y, border + TextWidth * GIF_FONT_WIDTH + border,
255 | border + LineCount * GIF_FONT_HEIGHT + border, fg);
256 | }
257 | }
258 |
259 | /* end */
260 |
--------------------------------------------------------------------------------
/giflib/src/main/cpp/giflib/gif_hash.c:
--------------------------------------------------------------------------------
1 | /*****************************************************************************
2 |
3 | gif_hash.c -- module to support the following operations:
4 |
5 | 1. InitHashTable - initialize hash table.
6 | 2. ClearHashTable - clear the hash table to an empty state.
7 | 2. InsertHashTable - insert one item into data structure.
8 | 3. ExistsHashTable - test if item exists in data structure.
9 |
10 | This module is used to hash the GIF codes during encoding.
11 |
12 | *****************************************************************************/
13 |
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 |
21 | #include "gif_lib.h"
22 | #include "gif_hash.h"
23 | #include "gif_lib_private.h"
24 |
25 | /* #define DEBUG_HIT_RATE Debug number of misses per hash Insert/Exists. */
26 |
27 | #ifdef DEBUG_HIT_RATE
28 | static long NumberOfTests = 0,
29 | NumberOfMisses = 0;
30 | #endif /* DEBUG_HIT_RATE */
31 |
32 | static int KeyItem(uint32_t Item);
33 |
34 | /******************************************************************************
35 | Initialize HashTable - allocate the memory needed and clear it. *
36 | ******************************************************************************/
37 | GifHashTableType *_InitHashTable(void)
38 | {
39 | GifHashTableType *HashTable;
40 |
41 | if ((HashTable = (GifHashTableType *) malloc(sizeof(GifHashTableType)))
42 | == NULL)
43 | return NULL;
44 |
45 | _ClearHashTable(HashTable);
46 |
47 | return HashTable;
48 | }
49 |
50 | /******************************************************************************
51 | Routine to clear the HashTable to an empty state. *
52 | This part is a little machine depended. Use the commented part otherwise. *
53 | ******************************************************************************/
54 | void _ClearHashTable(GifHashTableType *HashTable)
55 | {
56 | memset(HashTable -> HTable, 0xFF, HT_SIZE * sizeof(uint32_t));
57 | }
58 |
59 | /******************************************************************************
60 | Routine to insert a new Item into the HashTable. The data is assumed to be *
61 | new one. *
62 | ******************************************************************************/
63 | void _InsertHashTable(GifHashTableType *HashTable, uint32_t Key, int Code)
64 | {
65 | int HKey = KeyItem(Key);
66 | uint32_t *HTable = HashTable -> HTable;
67 |
68 | #ifdef DEBUG_HIT_RATE
69 | NumberOfTests++;
70 | NumberOfMisses++;
71 | #endif /* DEBUG_HIT_RATE */
72 |
73 | while (HT_GET_KEY(HTable[HKey]) != 0xFFFFFL) {
74 | #ifdef DEBUG_HIT_RATE
75 | NumberOfMisses++;
76 | #endif /* DEBUG_HIT_RATE */
77 | HKey = (HKey + 1) & HT_KEY_MASK;
78 | }
79 | HTable[HKey] = HT_PUT_KEY(Key) | HT_PUT_CODE(Code);
80 | }
81 |
82 | /******************************************************************************
83 | Routine to test if given Key exists in HashTable and if so returns its code *
84 | Returns the Code if key was found, -1 if not. *
85 | ******************************************************************************/
86 | int _ExistsHashTable(GifHashTableType *HashTable, uint32_t Key)
87 | {
88 | int HKey = KeyItem(Key);
89 | uint32_t *HTable = HashTable -> HTable, HTKey;
90 |
91 | #ifdef DEBUG_HIT_RATE
92 | NumberOfTests++;
93 | NumberOfMisses++;
94 | #endif /* DEBUG_HIT_RATE */
95 |
96 | while ((HTKey = HT_GET_KEY(HTable[HKey])) != 0xFFFFFL) {
97 | #ifdef DEBUG_HIT_RATE
98 | NumberOfMisses++;
99 | #endif /* DEBUG_HIT_RATE */
100 | if (Key == HTKey) return HT_GET_CODE(HTable[HKey]);
101 | HKey = (HKey + 1) & HT_KEY_MASK;
102 | }
103 |
104 | return -1;
105 | }
106 |
107 | /******************************************************************************
108 | Routine to generate an HKey for the hashtable out of the given unique key. *
109 | The given Key is assumed to be 20 bits as follows: lower 8 bits are the *
110 | new postfix character, while the upper 12 bits are the prefix code. *
111 | Because the average hit ratio is only 2 (2 hash references per entry), *
112 | evaluating more complex keys (such as twin prime keys) does not worth it! *
113 | ******************************************************************************/
114 | static int KeyItem(uint32_t Item)
115 | {
116 | return ((Item >> 12) ^ Item) & HT_KEY_MASK;
117 | }
118 |
119 | #ifdef DEBUG_HIT_RATE
120 | /******************************************************************************
121 | Debugging routine to print the hit ratio - number of times the hash table *
122 | was tested per operation. This routine was used to test the KeyItem routine *
123 | ******************************************************************************/
124 | void HashTablePrintHitRatio(void)
125 | {
126 | printf("Hash Table Hit Ratio is %ld/%ld = %ld%%.\n",
127 | NumberOfMisses, NumberOfTests,
128 | NumberOfMisses * 100 / NumberOfTests);
129 | }
130 | #endif /* DEBUG_HIT_RATE */
131 |
132 | /* end */
133 |
--------------------------------------------------------------------------------
/giflib/src/main/cpp/giflib/gif_hash.h:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 |
3 | gif_hash.h - magfic constants and declarations for GIF LZW
4 |
5 | ******************************************************************************/
6 |
7 | #ifndef _GIF_HASH_H_
8 | #define _GIF_HASH_H_
9 |
10 | #include
11 | #include
12 |
13 | #define HT_SIZE 8192 /* 12bits = 4096 or twice as big! */
14 | #define HT_KEY_MASK 0x1FFF /* 13bits keys */
15 | #define HT_KEY_NUM_BITS 13 /* 13bits keys */
16 | #define HT_MAX_KEY 8191 /* 13bits - 1, maximal code possible */
17 | #define HT_MAX_CODE 4095 /* Biggest code possible in 12 bits. */
18 |
19 | /* The 32 bits of the long are divided into two parts for the key & code: */
20 | /* 1. The code is 12 bits as our compression algorithm is limited to 12bits */
21 | /* 2. The key is 12 bits Prefix code + 8 bit new char or 20 bits. */
22 | /* The key is the upper 20 bits. The code is the lower 12. */
23 | #define HT_GET_KEY(l) (l >> 12)
24 | #define HT_GET_CODE(l) (l & 0x0FFF)
25 | #define HT_PUT_KEY(l) (l << 12)
26 | #define HT_PUT_CODE(l) (l & 0x0FFF)
27 |
28 | typedef struct GifHashTableType {
29 | uint32_t HTable[HT_SIZE];
30 | } GifHashTableType;
31 |
32 | GifHashTableType *_InitHashTable(void);
33 | void _ClearHashTable(GifHashTableType *HashTable);
34 | void _InsertHashTable(GifHashTableType *HashTable, uint32_t Key, int Code);
35 | int _ExistsHashTable(GifHashTableType *HashTable, uint32_t Key);
36 |
37 | #endif /* _GIF_HASH_H_ */
38 |
39 | /* end */
40 |
--------------------------------------------------------------------------------
/giflib/src/main/cpp/giflib/gif_lib.h:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 |
3 | gif_lib.h - service library for decoding and encoding GIF images
4 |
5 | *****************************************************************************/
6 |
7 | #ifndef _GIF_LIB_H_
8 | #define _GIF_LIB_H_ 1
9 |
10 | #ifdef __cplusplus
11 | extern "C" {
12 | #endif /* __cplusplus */
13 |
14 | #define GIFLIB_MAJOR 5
15 | #define GIFLIB_MINOR 1
16 | #define GIFLIB_RELEASE 4
17 |
18 | #define GIF_ERROR 0
19 | #define GIF_OK 1
20 |
21 | #include
22 | #include
23 |
24 | #define GIF_STAMP "GIFVER" /* First chars in file - GIF stamp. */
25 | #define GIF_STAMP_LEN sizeof(GIF_STAMP) - 1
26 | #define GIF_VERSION_POS 3 /* Version first character in stamp. */
27 | #define GIF87_STAMP "GIF87a" /* First chars in file - GIF stamp. */
28 | #define GIF89_STAMP "GIF89a" /* First chars in file - GIF stamp. */
29 |
30 | typedef unsigned char GifPixelType;
31 | typedef unsigned char *GifRowType;
32 | typedef unsigned char GifByteType;
33 | typedef unsigned int GifPrefixType;
34 | typedef int GifWord;
35 |
36 | typedef struct GifColorType {
37 | GifByteType Red, Green, Blue;
38 | } GifColorType;
39 |
40 | typedef struct ColorMapObject {
41 | int ColorCount;
42 | int BitsPerPixel;
43 | bool SortFlag;
44 | GifColorType *Colors; /* on malloc(3) heap */
45 | } ColorMapObject;
46 |
47 | typedef struct GifImageDesc {
48 | GifWord Left, Top, Width, Height; /* Current image dimensions. */
49 | bool Interlace; /* Sequential/Interlaced lines. */
50 | ColorMapObject *ColorMap; /* The local color map */
51 | } GifImageDesc;
52 |
53 | typedef struct ExtensionBlock {
54 | int ByteCount;
55 | GifByteType *Bytes; /* on malloc(3) heap */
56 | int Function; /* The block function code */
57 | #define CONTINUE_EXT_FUNC_CODE 0x00 /* continuation subblock */
58 | #define COMMENT_EXT_FUNC_CODE 0xfe /* comment */
59 | #define GRAPHICS_EXT_FUNC_CODE 0xf9 /* graphics control (GIF89) */
60 | #define PLAINTEXT_EXT_FUNC_CODE 0x01 /* plaintext */
61 | #define APPLICATION_EXT_FUNC_CODE 0xff /* application block */
62 | } ExtensionBlock;
63 |
64 | typedef struct SavedImage {
65 | GifImageDesc ImageDesc;
66 | GifByteType *RasterBits; /* on malloc(3) heap */
67 | int ExtensionBlockCount; /* Count of extensions before image */
68 | ExtensionBlock *ExtensionBlocks; /* Extensions before image */
69 | } SavedImage;
70 |
71 | typedef struct GifFileType {
72 | GifWord SWidth, SHeight; /* Size of virtual canvas */
73 | GifWord SColorResolution; /* How many colors can we generate? */
74 | GifWord SBackGroundColor; /* Background color for virtual canvas */
75 | GifByteType AspectByte; /* Used to compute pixel aspect ratio */
76 | ColorMapObject *SColorMap; /* Global colormap, NULL if nonexistent. */
77 | int ImageCount; /* Number of current image (both APIs) */
78 | GifImageDesc Image; /* Current image (low-level API) */
79 | SavedImage *SavedImages; /* Image sequence (high-level API) */
80 | int ExtensionBlockCount; /* Count extensions past last image */
81 | ExtensionBlock *ExtensionBlocks; /* Extensions past last image */
82 | int Error; /* Last error condition reported */
83 | void *UserData; /* hook to attach user data (TVT) */
84 | void *Private; /* Don't mess with this! */
85 | } GifFileType;
86 |
87 | #define GIF_ASPECT_RATIO(n) ((n)+15.0/64.0)
88 |
89 | typedef enum {
90 | UNDEFINED_RECORD_TYPE,
91 | SCREEN_DESC_RECORD_TYPE,
92 | IMAGE_DESC_RECORD_TYPE, /* Begin with ',' */
93 | EXTENSION_RECORD_TYPE, /* Begin with '!' */
94 | TERMINATE_RECORD_TYPE /* Begin with ';' */
95 | } GifRecordType;
96 |
97 | /* func type to read gif data from arbitrary sources (TVT) */
98 | typedef int (*InputFunc) (GifFileType *, GifByteType *, int);
99 |
100 | /* func type to write gif data to arbitrary targets.
101 | * Returns count of bytes written. (MRB)
102 | */
103 | typedef int (*OutputFunc) (GifFileType *, const GifByteType *, int);
104 |
105 | /******************************************************************************
106 | GIF89 structures
107 | ******************************************************************************/
108 |
109 | typedef struct GraphicsControlBlock {
110 | int DisposalMode;
111 | #define DISPOSAL_UNSPECIFIED 0 /* No disposal specified. */
112 | #define DISPOSE_DO_NOT 1 /* Leave image in place */
113 | #define DISPOSE_BACKGROUND 2 /* Set area too background color */
114 | #define DISPOSE_PREVIOUS 3 /* Restore to previous content */
115 | bool UserInputFlag; /* User confirmation required before disposal */
116 | int DelayTime; /* pre-display delay in 0.01sec units */
117 | int TransparentColor; /* Palette index for transparency, -1 if none */
118 | #define NO_TRANSPARENT_COLOR -1
119 | } GraphicsControlBlock;
120 |
121 | /******************************************************************************
122 | GIF encoding routines
123 | ******************************************************************************/
124 |
125 | /* Main entry points */
126 | GifFileType *EGifOpenFileName(const char *GifFileName,
127 | const bool GifTestExistence, int *Error);
128 | GifFileType *EGifOpenFileHandle(const int GifFileHandle, int *Error);
129 | GifFileType *EGifOpen(void *userPtr, OutputFunc writeFunc, int *Error);
130 | int EGifSpew(GifFileType * GifFile);
131 | const char *EGifGetGifVersion(GifFileType *GifFile); /* new in 5.x */
132 | int EGifCloseFile(GifFileType *GifFile, int *ErrorCode);
133 |
134 | #define E_GIF_SUCCEEDED 0
135 | #define E_GIF_ERR_OPEN_FAILED 1 /* And EGif possible errors. */
136 | #define E_GIF_ERR_WRITE_FAILED 2
137 | #define E_GIF_ERR_HAS_SCRN_DSCR 3
138 | #define E_GIF_ERR_HAS_IMAG_DSCR 4
139 | #define E_GIF_ERR_NO_COLOR_MAP 5
140 | #define E_GIF_ERR_DATA_TOO_BIG 6
141 | #define E_GIF_ERR_NOT_ENOUGH_MEM 7
142 | #define E_GIF_ERR_DISK_IS_FULL 8
143 | #define E_GIF_ERR_CLOSE_FAILED 9
144 | #define E_GIF_ERR_NOT_WRITEABLE 10
145 |
146 | /* These are legacy. You probably do not want to call them directly */
147 | int EGifPutScreenDesc(GifFileType *GifFile,
148 | const int GifWidth, const int GifHeight,
149 | const int GifColorRes,
150 | const int GifBackGround,
151 | const ColorMapObject *GifColorMap);
152 | int EGifPutImageDesc(GifFileType *GifFile,
153 | const int GifLeft, const int GifTop,
154 | const int GifWidth, const int GifHeight,
155 | const bool GifInterlace,
156 | const ColorMapObject *GifColorMap);
157 | void EGifSetGifVersion(GifFileType *GifFile, const bool gif89);
158 | int EGifPutLine(GifFileType *GifFile, GifPixelType *GifLine,
159 | int GifLineLen);
160 | int EGifPutPixel(GifFileType *GifFile, const GifPixelType GifPixel);
161 | int EGifPutComment(GifFileType *GifFile, const char *GifComment);
162 | int EGifPutExtensionLeader(GifFileType *GifFile, const int GifExtCode);
163 | int EGifPutExtensionBlock(GifFileType *GifFile,
164 | const int GifExtLen, const void *GifExtension);
165 | int EGifPutExtensionTrailer(GifFileType *GifFile);
166 | int EGifPutExtension(GifFileType *GifFile, const int GifExtCode,
167 | const int GifExtLen,
168 | const void *GifExtension);
169 | int EGifPutCode(GifFileType *GifFile, int GifCodeSize,
170 | const GifByteType *GifCodeBlock);
171 | int EGifPutCodeNext(GifFileType *GifFile,
172 | const GifByteType *GifCodeBlock);
173 |
174 | /******************************************************************************
175 | GIF decoding routines
176 | ******************************************************************************/
177 |
178 | /* Main entry points */
179 | GifFileType *DGifOpenFileName(const char *GifFileName, int *Error);
180 | GifFileType *DGifOpenFileHandle(int GifFileHandle, int *Error);
181 | int DGifSlurp(GifFileType * GifFile);
182 | GifFileType *DGifOpen(void *userPtr, InputFunc readFunc, int *Error); /* new one (TVT) */
183 | int DGifCloseFile(GifFileType * GifFile, int *ErrorCode);
184 |
185 | #define D_GIF_SUCCEEDED 0
186 | #define D_GIF_ERR_OPEN_FAILED 101 /* And DGif possible errors. */
187 | #define D_GIF_ERR_READ_FAILED 102
188 | #define D_GIF_ERR_NOT_GIF_FILE 103
189 | #define D_GIF_ERR_NO_SCRN_DSCR 104
190 | #define D_GIF_ERR_NO_IMAG_DSCR 105
191 | #define D_GIF_ERR_NO_COLOR_MAP 106
192 | #define D_GIF_ERR_WRONG_RECORD 107
193 | #define D_GIF_ERR_DATA_TOO_BIG 108
194 | #define D_GIF_ERR_NOT_ENOUGH_MEM 109
195 | #define D_GIF_ERR_CLOSE_FAILED 110
196 | #define D_GIF_ERR_NOT_READABLE 111
197 | #define D_GIF_ERR_IMAGE_DEFECT 112
198 | #define D_GIF_ERR_EOF_TOO_SOON 113
199 |
200 | /* These are legacy. You probably do not want to call them directly */
201 | int DGifGetScreenDesc(GifFileType *GifFile);
202 | int DGifGetRecordType(GifFileType *GifFile, GifRecordType *GifType);
203 | int DGifGetImageDesc(GifFileType *GifFile);
204 | int DGifGetLine(GifFileType *GifFile, GifPixelType *GifLine, int GifLineLen);
205 | int DGifGetPixel(GifFileType *GifFile, GifPixelType GifPixel);
206 | int DGifGetComment(GifFileType *GifFile, char *GifComment);
207 | int DGifGetExtension(GifFileType *GifFile, int *GifExtCode,
208 | GifByteType **GifExtension);
209 | int DGifGetExtensionNext(GifFileType *GifFile, GifByteType **GifExtension);
210 | int DGifGetCode(GifFileType *GifFile, int *GifCodeSize,
211 | GifByteType **GifCodeBlock);
212 | int DGifGetCodeNext(GifFileType *GifFile, GifByteType **GifCodeBlock);
213 | int DGifGetLZCodes(GifFileType *GifFile, int *GifCode);
214 |
215 |
216 | /******************************************************************************
217 | Color table quantization (deprecated)
218 | ******************************************************************************/
219 | int GifQuantizeBuffer(unsigned int Width, unsigned int Height,
220 | int *ColorMapSize, GifByteType * RedInput,
221 | GifByteType * GreenInput, GifByteType * BlueInput,
222 | GifByteType * OutputBuffer,
223 | GifColorType * OutputColorMap);
224 |
225 | /******************************************************************************
226 | Error handling and reporting.
227 | ******************************************************************************/
228 | extern const char *GifErrorString(int ErrorCode); /* new in 2012 - ESR */
229 |
230 | /*****************************************************************************
231 | Everything below this point is new after version 1.2, supporting `slurp
232 | mode' for doing I/O in two big belts with all the image-bashing in core.
233 | ******************************************************************************/
234 |
235 | /******************************************************************************
236 | Color map handling from gif_alloc.c
237 | ******************************************************************************/
238 |
239 | extern ColorMapObject *GifMakeMapObject(int ColorCount,
240 | const GifColorType *ColorMap);
241 | extern void GifFreeMapObject(ColorMapObject *Object);
242 | extern ColorMapObject *GifUnionColorMap(const ColorMapObject *ColorIn1,
243 | const ColorMapObject *ColorIn2,
244 | GifPixelType ColorTransIn2[]);
245 | extern int GifBitSize(int n);
246 |
247 | extern void *
248 | reallocarray(void *optr, size_t nmemb, size_t size);
249 |
250 | /******************************************************************************
251 | Support for the in-core structures allocation (slurp mode).
252 | ******************************************************************************/
253 |
254 | extern void GifApplyTranslation(SavedImage *Image, GifPixelType Translation[]);
255 | extern int GifAddExtensionBlock(int *ExtensionBlock_Count,
256 | ExtensionBlock **ExtensionBlocks,
257 | int Function,
258 | unsigned int Len, unsigned char ExtData[]);
259 | extern void GifFreeExtensions(int *ExtensionBlock_Count,
260 | ExtensionBlock **ExtensionBlocks);
261 | extern SavedImage *GifMakeSavedImage(GifFileType *GifFile,
262 | const SavedImage *CopyFrom);
263 | extern void GifFreeSavedImages(GifFileType *GifFile);
264 |
265 | /******************************************************************************
266 | 5.x functions for GIF89 graphics control blocks
267 | ******************************************************************************/
268 |
269 | int DGifExtensionToGCB(const size_t GifExtensionLength,
270 | const GifByteType *GifExtension,
271 | GraphicsControlBlock *GCB);
272 | size_t EGifGCBToExtension(const GraphicsControlBlock *GCB,
273 | GifByteType *GifExtension);
274 |
275 | int DGifSavedExtensionToGCB(GifFileType *GifFile,
276 | int ImageIndex,
277 | GraphicsControlBlock *GCB);
278 | int EGifGCBToSavedExtension(const GraphicsControlBlock *GCB,
279 | GifFileType *GifFile,
280 | int ImageIndex);
281 |
282 | /******************************************************************************
283 | The library's internal utility font
284 | ******************************************************************************/
285 |
286 | #define GIF_FONT_WIDTH 8
287 | #define GIF_FONT_HEIGHT 8
288 | extern const unsigned char GifAsciiTable8x8[][GIF_FONT_WIDTH];
289 |
290 | extern void GifDrawText8x8(SavedImage *Image,
291 | const int x, const int y,
292 | const char *legend, const int color);
293 |
294 | extern void GifDrawBox(SavedImage *Image,
295 | const int x, const int y,
296 | const int w, const int d, const int color);
297 |
298 | extern void GifDrawRectangle(SavedImage *Image,
299 | const int x, const int y,
300 | const int w, const int d, const int color);
301 |
302 | extern void GifDrawBoxedText8x8(SavedImage *Image,
303 | const int x, const int y,
304 | const char *legend,
305 | const int border, const int bg, const int fg);
306 |
307 | #ifdef __cplusplus
308 | }
309 | #endif /* __cplusplus */
310 | #endif /* _GIF_LIB_H */
311 |
312 | /* end */
313 |
--------------------------------------------------------------------------------
/giflib/src/main/cpp/giflib/gif_lib_private.h:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 |
3 | gif_lib_private.h - internal giflib routines and structures
4 |
5 | ****************************************************************************/
6 |
7 | #ifndef _GIF_LIB_PRIVATE_H
8 | #define _GIF_LIB_PRIVATE_H
9 |
10 | #include "gif_lib.h"
11 | #include "gif_hash.h"
12 |
13 | #define EXTENSION_INTRODUCER 0x21
14 | #define DESCRIPTOR_INTRODUCER 0x2c
15 | #define TERMINATOR_INTRODUCER 0x3b
16 |
17 | #define LZ_MAX_CODE 4095 /* Biggest code possible in 12 bits. */
18 | #define LZ_BITS 12
19 |
20 | #define FLUSH_OUTPUT 4096 /* Impossible code, to signal flush. */
21 | #define FIRST_CODE 4097 /* Impossible code, to signal first. */
22 | #define NO_SUCH_CODE 4098 /* Impossible code, to signal empty. */
23 |
24 | #define FILE_STATE_WRITE 0x01
25 | #define FILE_STATE_SCREEN 0x02
26 | #define FILE_STATE_IMAGE 0x04
27 | #define FILE_STATE_READ 0x08
28 |
29 | #define IS_READABLE(Private) (Private->FileState & FILE_STATE_READ)
30 | #define IS_WRITEABLE(Private) (Private->FileState & FILE_STATE_WRITE)
31 |
32 | typedef struct GifFilePrivateType {
33 | GifWord FileState, FileHandle, /* Where all this data goes to! */
34 | BitsPerPixel, /* Bits per pixel (Codes uses at least this + 1). */
35 | ClearCode, /* The CLEAR LZ code. */
36 | EOFCode, /* The EOF LZ code. */
37 | RunningCode, /* The next code algorithm can generate. */
38 | RunningBits, /* The number of bits required to represent RunningCode. */
39 | MaxCode1, /* 1 bigger than max. possible code, in RunningBits bits. */
40 | LastCode, /* The code before the current code. */
41 | CrntCode, /* Current algorithm code. */
42 | StackPtr, /* For character stack (see below). */
43 | CrntShiftState; /* Number of bits in CrntShiftDWord. */
44 | unsigned long CrntShiftDWord; /* For bytes decomposition into codes. */
45 | unsigned long PixelCount; /* Number of pixels in image. */
46 | FILE *File; /* File as stream. */
47 | InputFunc Read; /* function to read gif input (TVT) */
48 | OutputFunc Write; /* function to write gif output (MRB) */
49 | GifByteType Buf[256]; /* Compressed input is buffered here. */
50 | GifByteType Stack[LZ_MAX_CODE]; /* Decoded pixels are stacked here. */
51 | GifByteType Suffix[LZ_MAX_CODE + 1]; /* So we can trace the codes. */
52 | GifPrefixType Prefix[LZ_MAX_CODE + 1];
53 | GifHashTableType *HashTable;
54 | bool gif89;
55 | } GifFilePrivateType;
56 |
57 | #endif /* _GIF_LIB_PRIVATE_H */
58 |
59 | /* end */
60 |
--------------------------------------------------------------------------------
/giflib/src/main/cpp/giflib/openbsd-reallocarray.c:
--------------------------------------------------------------------------------
1 | /* $OpenBSD: reallocarray.c,v 1.1 2014/05/08 21:43:49 deraadt Exp $ */
2 | /*
3 | * Copyright (c) 2008 Otto Moerbeek
4 | *
5 | * Permission to use, copy, modify, and distribute this software for any
6 | * purpose with or without fee is hereby granted, provided that the above
7 | * copyright notice and this permission notice appear in all copies.
8 | *
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | */
17 |
18 | #include
19 | #include
20 | #include
21 | #include
22 |
23 | /*
24 | * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
25 | * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
26 | */
27 | #define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
28 |
29 | void *
30 | reallocarray(void *optr, size_t nmemb, size_t size)
31 | {
32 | if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
33 | nmemb > 0 && SIZE_MAX / nmemb < size) {
34 | errno = ENOMEM;
35 | return NULL;
36 | }
37 | return realloc(optr, size * nmemb);
38 | }
39 |
--------------------------------------------------------------------------------
/giflib/src/main/cpp/giflib/quantize.c:
--------------------------------------------------------------------------------
1 | /*****************************************************************************
2 |
3 | quantize.c - quantize a high resolution image into lower one
4 |
5 | Based on: "Color Image Quantization for frame buffer Display", by
6 | Paul Heckbert SIGGRAPH 1982 page 297-307.
7 |
8 | This doesn't really belong in the core library, was undocumented,
9 | and was removed in 4.2. Then it turned out some client apps were
10 | actually using it, so it was restored in 5.0.
11 |
12 | ******************************************************************************/
13 |
14 | #include
15 | #include
16 | #include "gif_lib.h"
17 | #include "gif_lib_private.h"
18 |
19 | #define ABS(x) ((x) > 0 ? (x) : (-(x)))
20 |
21 | #define COLOR_ARRAY_SIZE 32768
22 | #define BITS_PER_PRIM_COLOR 5
23 | #define MAX_PRIM_COLOR 0x1f
24 |
25 | static int SortRGBAxis;
26 |
27 | typedef struct QuantizedColorType {
28 | GifByteType RGB[3];
29 | GifByteType NewColorIndex;
30 | long Count;
31 | struct QuantizedColorType *Pnext;
32 | } QuantizedColorType;
33 |
34 | typedef struct NewColorMapType {
35 | GifByteType RGBMin[3], RGBWidth[3];
36 | unsigned int NumEntries; /* # of QuantizedColorType in linked list below */
37 | unsigned long Count; /* Total number of pixels in all the entries */
38 | QuantizedColorType *QuantizedColors;
39 | } NewColorMapType;
40 |
41 | static int SubdivColorMap(NewColorMapType * NewColorSubdiv,
42 | unsigned int ColorMapSize,
43 | unsigned int *NewColorMapSize);
44 | static int SortCmpRtn(const void *Entry1, const void *Entry2);
45 |
46 | /******************************************************************************
47 | Quantize high resolution image into lower one. Input image consists of a
48 | 2D array for each of the RGB colors with size Width by Height. There is no
49 | Color map for the input. Output is a quantized image with 2D array of
50 | indexes into the output color map.
51 | Note input image can be 24 bits at the most (8 for red/green/blue) and
52 | the output has 256 colors at the most (256 entries in the color map.).
53 | ColorMapSize specifies size of color map up to 256 and will be updated to
54 | real size before returning.
55 | Also non of the parameter are allocated by this routine.
56 | This function returns GIF_OK if successful, GIF_ERROR otherwise.
57 | ******************************************************************************/
58 | int
59 | GifQuantizeBuffer(unsigned int Width,
60 | unsigned int Height,
61 | int *ColorMapSize,
62 | GifByteType * RedInput,
63 | GifByteType * GreenInput,
64 | GifByteType * BlueInput,
65 | GifByteType * OutputBuffer,
66 | GifColorType * OutputColorMap) {
67 |
68 | unsigned int Index, NumOfEntries;
69 | int i, j, MaxRGBError[3];
70 | unsigned int NewColorMapSize;
71 | long Red, Green, Blue;
72 | NewColorMapType NewColorSubdiv[256];
73 | QuantizedColorType *ColorArrayEntries, *QuantizedColor;
74 |
75 | ColorArrayEntries = (QuantizedColorType *)malloc(
76 | sizeof(QuantizedColorType) * COLOR_ARRAY_SIZE);
77 | if (ColorArrayEntries == NULL) {
78 | return GIF_ERROR;
79 | }
80 |
81 | for (i = 0; i < COLOR_ARRAY_SIZE; i++) {
82 | ColorArrayEntries[i].RGB[0] = i >> (2 * BITS_PER_PRIM_COLOR);
83 | ColorArrayEntries[i].RGB[1] = (i >> BITS_PER_PRIM_COLOR) &
84 | MAX_PRIM_COLOR;
85 | ColorArrayEntries[i].RGB[2] = i & MAX_PRIM_COLOR;
86 | ColorArrayEntries[i].Count = 0;
87 | }
88 |
89 | /* Sample the colors and their distribution: */
90 | for (i = 0; i < (int)(Width * Height); i++) {
91 | Index = ((RedInput[i] >> (8 - BITS_PER_PRIM_COLOR)) <<
92 | (2 * BITS_PER_PRIM_COLOR)) +
93 | ((GreenInput[i] >> (8 - BITS_PER_PRIM_COLOR)) <<
94 | BITS_PER_PRIM_COLOR) +
95 | (BlueInput[i] >> (8 - BITS_PER_PRIM_COLOR));
96 | ColorArrayEntries[Index].Count++;
97 | }
98 |
99 | /* Put all the colors in the first entry of the color map, and call the
100 | * recursive subdivision process. */
101 | for (i = 0; i < 256; i++) {
102 | NewColorSubdiv[i].QuantizedColors = NULL;
103 | NewColorSubdiv[i].Count = NewColorSubdiv[i].NumEntries = 0;
104 | for (j = 0; j < 3; j++) {
105 | NewColorSubdiv[i].RGBMin[j] = 0;
106 | NewColorSubdiv[i].RGBWidth[j] = 255;
107 | }
108 | }
109 |
110 | /* Find the non empty entries in the color table and chain them: */
111 | for (i = 0; i < COLOR_ARRAY_SIZE; i++)
112 | if (ColorArrayEntries[i].Count > 0)
113 | break;
114 | QuantizedColor = NewColorSubdiv[0].QuantizedColors = &ColorArrayEntries[i];
115 | NumOfEntries = 1;
116 | while (++i < COLOR_ARRAY_SIZE)
117 | if (ColorArrayEntries[i].Count > 0) {
118 | QuantizedColor->Pnext = &ColorArrayEntries[i];
119 | QuantizedColor = &ColorArrayEntries[i];
120 | NumOfEntries++;
121 | }
122 | QuantizedColor->Pnext = NULL;
123 |
124 | NewColorSubdiv[0].NumEntries = NumOfEntries; /* Different sampled colors */
125 | NewColorSubdiv[0].Count = ((long)Width) * Height; /* Pixels */
126 | NewColorMapSize = 1;
127 | if (SubdivColorMap(NewColorSubdiv, *ColorMapSize, &NewColorMapSize) !=
128 | GIF_OK) {
129 | free((char *)ColorArrayEntries);
130 | return GIF_ERROR;
131 | }
132 | if (NewColorMapSize < *ColorMapSize) {
133 | /* And clear rest of color map: */
134 | for (i = NewColorMapSize; i < *ColorMapSize; i++)
135 | OutputColorMap[i].Red = OutputColorMap[i].Green =
136 | OutputColorMap[i].Blue = 0;
137 | }
138 |
139 | /* Average the colors in each entry to be the color to be used in the
140 | * output color map, and plug it into the output color map itself. */
141 | for (i = 0; i < NewColorMapSize; i++) {
142 | if ((j = NewColorSubdiv[i].NumEntries) > 0) {
143 | QuantizedColor = NewColorSubdiv[i].QuantizedColors;
144 | Red = Green = Blue = 0;
145 | while (QuantizedColor) {
146 | QuantizedColor->NewColorIndex = i;
147 | Red += QuantizedColor->RGB[0];
148 | Green += QuantizedColor->RGB[1];
149 | Blue += QuantizedColor->RGB[2];
150 | QuantizedColor = QuantizedColor->Pnext;
151 | }
152 | OutputColorMap[i].Red = (Red << (8 - BITS_PER_PRIM_COLOR)) / j;
153 | OutputColorMap[i].Green = (Green << (8 - BITS_PER_PRIM_COLOR)) / j;
154 | OutputColorMap[i].Blue = (Blue << (8 - BITS_PER_PRIM_COLOR)) / j;
155 | }
156 | }
157 |
158 | /* Finally scan the input buffer again and put the mapped index in the
159 | * output buffer. */
160 | MaxRGBError[0] = MaxRGBError[1] = MaxRGBError[2] = 0;
161 | for (i = 0; i < (int)(Width * Height); i++) {
162 | Index = ((RedInput[i] >> (8 - BITS_PER_PRIM_COLOR)) <<
163 | (2 * BITS_PER_PRIM_COLOR)) +
164 | ((GreenInput[i] >> (8 - BITS_PER_PRIM_COLOR)) <<
165 | BITS_PER_PRIM_COLOR) +
166 | (BlueInput[i] >> (8 - BITS_PER_PRIM_COLOR));
167 | Index = ColorArrayEntries[Index].NewColorIndex;
168 | OutputBuffer[i] = Index;
169 | if (MaxRGBError[0] < ABS(OutputColorMap[Index].Red - RedInput[i]))
170 | MaxRGBError[0] = ABS(OutputColorMap[Index].Red - RedInput[i]);
171 | if (MaxRGBError[1] < ABS(OutputColorMap[Index].Green - GreenInput[i]))
172 | MaxRGBError[1] = ABS(OutputColorMap[Index].Green - GreenInput[i]);
173 | if (MaxRGBError[2] < ABS(OutputColorMap[Index].Blue - BlueInput[i]))
174 | MaxRGBError[2] = ABS(OutputColorMap[Index].Blue - BlueInput[i]);
175 | }
176 |
177 | #ifdef DEBUG
178 | fprintf(stderr,
179 | "Quantization L(0) errors: Red = %d, Green = %d, Blue = %d.\n",
180 | MaxRGBError[0], MaxRGBError[1], MaxRGBError[2]);
181 | #endif /* DEBUG */
182 |
183 | free((char *)ColorArrayEntries);
184 |
185 | *ColorMapSize = NewColorMapSize;
186 |
187 | return GIF_OK;
188 | }
189 |
190 | /******************************************************************************
191 | Routine to subdivide the RGB space recursively using median cut in each
192 | axes alternatingly until ColorMapSize different cubes exists.
193 | The biggest cube in one dimension is subdivide unless it has only one entry.
194 | Returns GIF_ERROR if failed, otherwise GIF_OK.
195 | *******************************************************************************/
196 | static int
197 | SubdivColorMap(NewColorMapType * NewColorSubdiv,
198 | unsigned int ColorMapSize,
199 | unsigned int *NewColorMapSize) {
200 |
201 | int MaxSize;
202 | unsigned int i, j, Index = 0, NumEntries, MinColor, MaxColor;
203 | long Sum, Count;
204 | QuantizedColorType *QuantizedColor, **SortArray;
205 |
206 | while (ColorMapSize > *NewColorMapSize) {
207 | /* Find candidate for subdivision: */
208 | MaxSize = -1;
209 | for (i = 0; i < *NewColorMapSize; i++) {
210 | for (j = 0; j < 3; j++) {
211 | if ((((int)NewColorSubdiv[i].RGBWidth[j]) > MaxSize) &&
212 | (NewColorSubdiv[i].NumEntries > 1)) {
213 | MaxSize = NewColorSubdiv[i].RGBWidth[j];
214 | Index = i;
215 | SortRGBAxis = j;
216 | }
217 | }
218 | }
219 |
220 | if (MaxSize == -1)
221 | return GIF_OK;
222 |
223 | /* Split the entry Index into two along the axis SortRGBAxis: */
224 |
225 | /* Sort all elements in that entry along the given axis and split at
226 | * the median. */
227 | SortArray = (QuantizedColorType **)malloc(
228 | sizeof(QuantizedColorType *) *
229 | NewColorSubdiv[Index].NumEntries);
230 | if (SortArray == NULL)
231 | return GIF_ERROR;
232 | for (j = 0, QuantizedColor = NewColorSubdiv[Index].QuantizedColors;
233 | j < NewColorSubdiv[Index].NumEntries && QuantizedColor != NULL;
234 | j++, QuantizedColor = QuantizedColor->Pnext)
235 | SortArray[j] = QuantizedColor;
236 |
237 | /*
238 | * Because qsort isn't stable, this can produce differing
239 | * results for the order of tuples depending on platform
240 | * details of how qsort() is implemented.
241 | *
242 | * We mitigate this problem by sorting on all three axes rather
243 | * than only the one specied by SortRGBAxis; that way the instability
244 | * can only become an issue if there are multiple color indices
245 | * referring to identical RGB tuples. Older versions of this
246 | * sorted on only the one axis.
247 | */
248 | qsort(SortArray, NewColorSubdiv[Index].NumEntries,
249 | sizeof(QuantizedColorType *), SortCmpRtn);
250 |
251 | /* Relink the sorted list into one: */
252 | for (j = 0; j < NewColorSubdiv[Index].NumEntries - 1; j++)
253 | SortArray[j]->Pnext = SortArray[j + 1];
254 | SortArray[NewColorSubdiv[Index].NumEntries - 1]->Pnext = NULL;
255 | NewColorSubdiv[Index].QuantizedColors = QuantizedColor = SortArray[0];
256 | free((char *)SortArray);
257 |
258 | /* Now simply add the Counts until we have half of the Count: */
259 | Sum = NewColorSubdiv[Index].Count / 2 - QuantizedColor->Count;
260 | NumEntries = 1;
261 | Count = QuantizedColor->Count;
262 | while (QuantizedColor->Pnext != NULL &&
263 | (Sum -= QuantizedColor->Pnext->Count) >= 0 &&
264 | QuantizedColor->Pnext->Pnext != NULL) {
265 | QuantizedColor = QuantizedColor->Pnext;
266 | NumEntries++;
267 | Count += QuantizedColor->Count;
268 | }
269 | /* Save the values of the last color of the first half, and first
270 | * of the second half so we can update the Bounding Boxes later.
271 | * Also as the colors are quantized and the BBoxes are full 0..255,
272 | * they need to be rescaled.
273 | */
274 | MaxColor = QuantizedColor->RGB[SortRGBAxis]; /* Max. of first half */
275 | /* coverity[var_deref_op] */
276 | MinColor = QuantizedColor->Pnext->RGB[SortRGBAxis]; /* of second */
277 | MaxColor <<= (8 - BITS_PER_PRIM_COLOR);
278 | MinColor <<= (8 - BITS_PER_PRIM_COLOR);
279 |
280 | /* Partition right here: */
281 | NewColorSubdiv[*NewColorMapSize].QuantizedColors =
282 | QuantizedColor->Pnext;
283 | QuantizedColor->Pnext = NULL;
284 | NewColorSubdiv[*NewColorMapSize].Count = Count;
285 | NewColorSubdiv[Index].Count -= Count;
286 | NewColorSubdiv[*NewColorMapSize].NumEntries =
287 | NewColorSubdiv[Index].NumEntries - NumEntries;
288 | NewColorSubdiv[Index].NumEntries = NumEntries;
289 | for (j = 0; j < 3; j++) {
290 | NewColorSubdiv[*NewColorMapSize].RGBMin[j] =
291 | NewColorSubdiv[Index].RGBMin[j];
292 | NewColorSubdiv[*NewColorMapSize].RGBWidth[j] =
293 | NewColorSubdiv[Index].RGBWidth[j];
294 | }
295 | NewColorSubdiv[*NewColorMapSize].RGBWidth[SortRGBAxis] =
296 | NewColorSubdiv[*NewColorMapSize].RGBMin[SortRGBAxis] +
297 | NewColorSubdiv[*NewColorMapSize].RGBWidth[SortRGBAxis] - MinColor;
298 | NewColorSubdiv[*NewColorMapSize].RGBMin[SortRGBAxis] = MinColor;
299 |
300 | NewColorSubdiv[Index].RGBWidth[SortRGBAxis] =
301 | MaxColor - NewColorSubdiv[Index].RGBMin[SortRGBAxis];
302 |
303 | (*NewColorMapSize)++;
304 | }
305 |
306 | return GIF_OK;
307 | }
308 |
309 | /****************************************************************************
310 | Routine called by qsort to compare two entries.
311 | *****************************************************************************/
312 |
313 | static int
314 | SortCmpRtn(const void *Entry1,
315 | const void *Entry2) {
316 | QuantizedColorType *entry1 = (*((QuantizedColorType **) Entry1));
317 | QuantizedColorType *entry2 = (*((QuantizedColorType **) Entry2));
318 |
319 | /* sort on all axes of the color space! */
320 | int hash1 = entry1->RGB[SortRGBAxis] * 256 * 256
321 | + entry1->RGB[(SortRGBAxis+1) % 3] * 256
322 | + entry1->RGB[(SortRGBAxis+2) % 3];
323 | int hash2 = entry2->RGB[SortRGBAxis] * 256 * 256
324 | + entry2->RGB[(SortRGBAxis+1) % 3] * 256
325 | + entry2->RGB[(SortRGBAxis+2) % 3];
326 |
327 | return hash1 - hash2;
328 | }
329 |
330 | /* end */
331 |
--------------------------------------------------------------------------------
/giflib/src/main/cpp/log.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Administrator on 11/17/2016.
3 | //
4 |
5 | #ifndef FACERECOGNITION_LOG_H
6 | #define FACERECOGNITION_LOG_H
7 |
8 | #define LOG_DEBUG true
9 |
10 | #define TAG "DMUI"
11 |
12 | #include
13 |
14 | #ifdef LOG_DEBUG
15 | #define LOGI(...) \
16 | __android_log_print(ANDROID_LOG_INFO,TAG,__VA_ARGS__)
17 |
18 | #define LOGD(...) \
19 | __android_log_print(ANDROID_LOG_DEBUG,TAG,__VA_ARGS__)
20 |
21 | #define LOGW(...) \
22 | __android_log_print(ANDROID_LOG_WARN,TAG,__VA_ARGS__)
23 |
24 | #define LOGE(...) \
25 | __android_log_print(ANDROID_LOG_ERROR,TAG,__VA_ARGS__)
26 | #else
27 | #define LOGI(...)
28 | #define LOGD(...)
29 | #define LOGW(...)
30 | #define LOGE(...)
31 | #endif
32 |
33 |
34 | #endif //FACERECOGNITION_LOG_H
35 |
--------------------------------------------------------------------------------
/giflib/src/main/java/com/dming/testgif/DLog.java:
--------------------------------------------------------------------------------
1 | package com.dming.testgif;
2 |
3 | import android.util.Log;
4 |
5 |
6 | /**
7 | * 简单日志类,方便
8 | * Created by DMing on 2017/9/19.
9 | */
10 |
11 | public class DLog {
12 |
13 | private static String TAG = "DMUI";
14 |
15 | public static void d(String msg){
16 | if (BuildConfig.DEBUG) Log.d(TAG,msg);
17 | }
18 |
19 | public static void i(String msg){
20 | if (BuildConfig.DEBUG) Log.i(TAG,msg);
21 | }
22 |
23 | public static void e(String msg){
24 | if (BuildConfig.DEBUG) Log.e(TAG,msg);
25 | }
26 |
27 | @SuppressWarnings("unused")
28 | public static void d(String tagNull, String msg) {
29 | d(msg);
30 | }
31 |
32 | @SuppressWarnings("unused")
33 | public static void i(String tagNull, String msg) {
34 | i(msg);
35 | }
36 |
37 | @SuppressWarnings("unused")
38 | public static void e(String tagNull, String msg) {
39 | e(msg);
40 | }
41 | }
--------------------------------------------------------------------------------
/giflib/src/main/java/com/dming/testgif/EglHelper.java:
--------------------------------------------------------------------------------
1 | package com.dming.testgif;
2 |
3 | import android.opengl.EGL14;
4 | import android.view.Surface;
5 |
6 | import javax.microedition.khronos.egl.EGL10;
7 | import javax.microedition.khronos.egl.EGLConfig;
8 | import javax.microedition.khronos.egl.EGLContext;
9 | import javax.microedition.khronos.egl.EGLDisplay;
10 | import javax.microedition.khronos.egl.EGLSurface;
11 |
12 | public class EglHelper {
13 | private static final String TAG = "EglHelper";
14 | private EGL10 mEgl;
15 | private EGLDisplay mEglDisplay;
16 | private EGLContext mEglContext;
17 | private EGLSurface mEglSurface;
18 |
19 |
20 | public void initEgl(EGLContext eglContext, Surface surface) {
21 | //1. 得到Egl实例
22 | mEgl = (EGL10) EGLContext.getEGL();
23 |
24 | //2. 得到默认的显示设备(就是窗口)
25 | mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
26 | if (mEglDisplay == EGL10.EGL_NO_DISPLAY) {
27 | throw new RuntimeException("eglGetDisplay failed");
28 | }
29 | //3. 初始化默认显示设备
30 | int[] version = new int[2];
31 | if (!mEgl.eglInitialize(mEglDisplay, version)) {
32 | throw new RuntimeException("eglInitialize failed");
33 | }
34 |
35 | //4. 设置显示设备的属性
36 | int[] attrib_list = new int[]{
37 | EGL10.EGL_RED_SIZE, mRedSize,
38 | EGL10.EGL_GREEN_SIZE, mGreenSize,
39 | EGL10.EGL_BLUE_SIZE, mBlueSize,
40 | EGL10.EGL_ALPHA_SIZE, mAlphaSize,
41 | EGL10.EGL_DEPTH_SIZE, mDepthSize,
42 | EGL10.EGL_STENCIL_SIZE, mStencilSize,
43 | EGL10.EGL_RENDERABLE_TYPE, mRenderType,//egl版本 2.0
44 | EGL10.EGL_NONE};
45 |
46 |
47 | int[] num_config = new int[1];
48 | if (!mEgl.eglChooseConfig(mEglDisplay, attrib_list, null, 1,
49 | num_config)) {
50 | throw new IllegalArgumentException("eglChooseConfig failed");
51 | }
52 | int numConfigs = num_config[0];
53 | if (numConfigs <= 0) {
54 | throw new IllegalArgumentException(
55 | "No configs match configSpec");
56 | }
57 |
58 | //5. 从系统中获取对应属性的配置
59 | EGLConfig[] configs = new EGLConfig[numConfigs];
60 | if (!mEgl.eglChooseConfig(mEglDisplay, attrib_list, configs, numConfigs,
61 | num_config)) {
62 | throw new IllegalArgumentException("eglChooseConfig#2 failed");
63 | }
64 | EGLConfig eglConfig = chooseConfig(mEgl, mEglDisplay, configs);
65 | if (eglConfig == null) {
66 | eglConfig = configs[0];
67 | }
68 |
69 | //6. 创建EglContext
70 | int[] contextAttr = new int[]{
71 | EGL14.EGL_CONTEXT_CLIENT_VERSION, 2,
72 | EGL10.EGL_NONE
73 | };
74 | if (eglContext == null) {
75 | mEglContext = mEgl.eglCreateContext(mEglDisplay, eglConfig, EGL10.EGL_NO_CONTEXT, contextAttr);
76 | } else {
77 | mEglContext = mEgl.eglCreateContext(mEglDisplay, eglConfig, eglContext, contextAttr);
78 | }
79 |
80 | //7. 创建渲染的Surface
81 | if (surface == null) {
82 | mEglSurface = EGL10.EGL_NO_SURFACE;
83 | // mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, eglConfig,surface,null);
84 | } else {
85 | mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, eglConfig, surface, null);
86 | }
87 | }
88 |
89 | public void glBindThread() {
90 | //8. 绑定EglContext和Surface到显示设备中
91 | if (mEglDisplay != null && mEglSurface != null && mEglContext != null) {
92 | if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
93 | throw new RuntimeException("eglMakeCurrent fail");
94 | }
95 | }
96 | }
97 |
98 |
99 | //9. 刷新数据,显示渲染场景
100 | public boolean swapBuffers() {
101 | if (mEgl != null) {
102 | return mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);
103 | } else {
104 | throw new RuntimeException("egl is null");
105 | }
106 | }
107 |
108 | public void destroyEgl() {
109 | if (mEgl != null) {
110 | if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) {
111 | mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,
112 | EGL10.EGL_NO_SURFACE,
113 | EGL10.EGL_NO_CONTEXT);
114 |
115 | mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
116 | mEglSurface = null;
117 | }
118 |
119 |
120 | if (mEglContext != null) {
121 | mEgl.eglDestroyContext(mEglDisplay, mEglContext);
122 | mEglContext = null;
123 | }
124 |
125 |
126 | if (mEglDisplay != null) {
127 | mEgl.eglTerminate(mEglDisplay);
128 | mEglDisplay = null;
129 | }
130 |
131 | mEgl = null;
132 | }
133 |
134 |
135 | }
136 |
137 |
138 | public EGLContext getEglContext() {
139 | return mEglContext;
140 | }
141 |
142 | private final int mRedSize = 8;
143 | private final int mGreenSize = 8;
144 | private final int mBlueSize = 8;
145 | private final int mAlphaSize = 8;
146 | private final int mDepthSize = 8;
147 | private final int mStencilSize = 8;
148 | private final int mRenderType = 4;
149 |
150 | private EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,
151 | EGLConfig[] configs) {
152 | for (EGLConfig config : configs) {
153 | int d = findConfigAttrib(egl, display, config,
154 | EGL10.EGL_DEPTH_SIZE, 0);
155 | int s = findConfigAttrib(egl, display, config,
156 | EGL10.EGL_STENCIL_SIZE, 0);
157 | if ((d >= mDepthSize) && (s >= mStencilSize)) {
158 | int r = findConfigAttrib(egl, display, config,
159 | EGL10.EGL_RED_SIZE, 0);
160 | int g = findConfigAttrib(egl, display, config,
161 | EGL10.EGL_GREEN_SIZE, 0);
162 | int b = findConfigAttrib(egl, display, config,
163 | EGL10.EGL_BLUE_SIZE, 0);
164 | int a = findConfigAttrib(egl, display, config,
165 | EGL10.EGL_ALPHA_SIZE, 0);
166 | if ((r == mRedSize) && (g == mGreenSize)
167 | && (b == mBlueSize) && (a == mAlphaSize)) {
168 | return config;
169 | }
170 | }
171 | }
172 | return null;
173 | }
174 |
175 | private int findConfigAttrib(EGL10 egl, EGLDisplay display,
176 | EGLConfig config, int attribute, int defaultValue) {
177 | int[] value = new int[1];
178 | if (egl.eglGetConfigAttrib(display, config, attribute, value)) {
179 | return value[0];
180 | }
181 | return defaultValue;
182 | }
183 | }
--------------------------------------------------------------------------------
/giflib/src/main/java/com/dming/testgif/FGLUtils.java:
--------------------------------------------------------------------------------
1 | package com.dming.testgif;
2 |
3 | import android.opengl.GLES11Ext;
4 | import android.opengl.GLES20;
5 |
6 | import javax.microedition.khronos.opengles.GL10;
7 |
8 | public class FGLUtils {
9 |
10 | public static int[] createFBO(int width, int height) {
11 | int[] mFrameBuffer = new int[1];
12 | int[] mFrameBufferTexture = new int[1];
13 | GLES20.glGenFramebuffers(1, mFrameBuffer, 0);
14 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFrameBuffer[0]);
15 | GLES20.glGenTextures(1, mFrameBufferTexture, 0);
16 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mFrameBufferTexture[0]);
17 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
18 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
19 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
20 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
21 | GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0,
22 | GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
23 | GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0,
24 | GLES20.GL_TEXTURE_2D, mFrameBufferTexture[0], 0);
25 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
26 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
27 | if (GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER) != GLES20.GL_FRAMEBUFFER_COMPLETE) {
28 | GLES20.glDeleteFramebuffers(1, mFrameBuffer, 0);
29 | GLES20.glDeleteTextures(1, mFrameBufferTexture, 0);
30 | DLog.e("create framebuffer failed");
31 | return null;
32 | }
33 | DLog.i("Java create framebuffer success: (" +
34 | width + ", " + height + "), FB: " + mFrameBuffer[0] + " , Tex: " + mFrameBufferTexture[0]);
35 | return new int[]{mFrameBuffer[0], mFrameBufferTexture[0]};
36 | }
37 |
38 | public static int createOESTexture() {
39 | int[] tex = new int[1];
40 | //生成一个纹理
41 | GLES20.glGenTextures(1, tex, 0);
42 | //将此纹理绑定到外部纹理上
43 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, tex[0]);
44 | //设置纹理过滤参数
45 | GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
46 | GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
47 | GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
48 | GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
49 | GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
50 | GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
51 | GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
52 | GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
53 | //解除纹理绑定
54 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0);
55 | return tex[0];
56 | }
57 |
58 | public static int createTexture() {
59 | int[] tex = new int[1];
60 | GLES20.glGenTextures(1, tex, 0);
61 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tex[0]);
62 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
63 | GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
64 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
65 | GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
66 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
67 | GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
68 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
69 | GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
70 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
71 | return tex[0];
72 | }
73 |
74 | public static void glCheckErr() {
75 | int err = GLES20.glGetError();
76 | DLog.i("checkErr: " + err);
77 | }
78 |
79 | public static void glCheckErr(String tag) {
80 | int err = GLES20.glGetError();
81 | if (err != 0) {
82 | DLog.i(tag + " > checkErr: " + err);
83 | }
84 | }
85 |
86 | public static void glCheckErr(int tag) {
87 | int err = GLES20.glGetError();
88 | DLog.i(tag + " > checkErr: " + err);
89 | }
90 |
91 | }
92 |
--------------------------------------------------------------------------------
/giflib/src/main/java/com/dming/testgif/GifFilter.java:
--------------------------------------------------------------------------------
1 | package com.dming.testgif;
2 |
3 | import android.content.Context;
4 | import android.opengl.GLES20;
5 | import android.opengl.Matrix;
6 |
7 | import java.nio.FloatBuffer;
8 | import java.nio.ShortBuffer;
9 |
10 | public class GifFilter {
11 |
12 | protected ShortBuffer mIndexSB;
13 | protected FloatBuffer mTexFB;
14 | protected FloatBuffer mPosFB;
15 | protected static final short[] VERTEX_INDEX = {
16 | 0, 1, 3,
17 | 2, 3, 1
18 | };
19 | protected static final float[] VERTEX_POS = {
20 | -1, 1.0f, 0f,
21 | -1, -1.0f, 0f,
22 | 1, -1.0f, 0f,
23 | 1, 1.0f, 0f,
24 | };
25 | public static final float[] TEX_VERTEX = {
26 | 0, 0,
27 | 0, 1,
28 | 1, 1,
29 | 1, 0,
30 | };
31 |
32 | protected int mProgram;
33 | protected int mPosition;
34 | protected int mTextureCoordinate;
35 | protected int mInputImageTexture;
36 | protected int uMvpMatrix;
37 | protected int uTexMatrix;
38 | protected float[] mMvpMatrix = new float[16];
39 | protected Context mContext;
40 |
41 | public GifFilter(Context context) {
42 | this.mContext = context;
43 | mIndexSB = ShaderHelper.arrayToShortBuffer(VERTEX_INDEX);
44 | mPosFB = ShaderHelper.arrayToFloatBuffer(VERTEX_POS);
45 | mTexFB = ShaderHelper.arrayToFloatBuffer(TEX_VERTEX);
46 | mProgram = ShaderHelper.loadProgram(context, com.dming.testgif.R.raw.gif_process_ver, com.dming.testgif.R.raw.gif_process_frg);
47 | mPosition = GLES20.glGetAttribLocation(mProgram, "inputPosition");
48 | mTextureCoordinate = GLES20.glGetAttribLocation(mProgram, "inputTextureCoordinate");
49 | mInputImageTexture = GLES20.glGetUniformLocation(mProgram, "inputImageTexture");
50 | uMvpMatrix = GLES20.glGetUniformLocation(mProgram, "inputMatrix");
51 | uTexMatrix = GLES20.glGetUniformLocation(mProgram, "uTexMatrix");
52 | Matrix.setIdentityM(mMvpMatrix, 0);
53 | FGLUtils.glCheckErr("NoFilter");
54 | }
55 |
56 | public void onDraw(int textureId, int x, int y, int width, int height) {
57 | GLES20.glUseProgram(mProgram);
58 | GLES20.glEnableVertexAttribArray(mPosition);
59 | GLES20.glVertexAttribPointer(mPosition, 3,
60 | GLES20.GL_FLOAT, false, 0, mPosFB);
61 | GLES20.glEnableVertexAttribArray(mTextureCoordinate);
62 | GLES20.glVertexAttribPointer(mTextureCoordinate, 2,
63 | GLES20.GL_FLOAT, false, 0, mTexFB);
64 | GLES20.glUniformMatrix4fv(uMvpMatrix, 1, false, mMvpMatrix, 0);
65 | GLES20.glUniformMatrix4fv(uTexMatrix, 1, false, mMvpMatrix, 0);
66 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
67 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
68 | GLES20.glUniform1i(mInputImageTexture, 0);
69 | GLES20.glViewport(x, y, width, height);
70 | GLES20.glDrawElements(GLES20.GL_TRIANGLES, VERTEX_INDEX.length,
71 | GLES20.GL_UNSIGNED_SHORT, mIndexSB);
72 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
73 | GLES20.glDisableVertexAttribArray(mPosition);
74 | GLES20.glDisableVertexAttribArray(mTextureCoordinate);
75 | GLES20.glUseProgram(0);
76 | }
77 |
78 | public void onDestroy() {
79 | GLES20.glDeleteProgram(mProgram);
80 | }
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/giflib/src/main/java/com/dming/testgif/GifPlayer.java:
--------------------------------------------------------------------------------
1 | package com.dming.testgif;
2 |
3 | import android.content.Context;
4 | import android.content.res.AssetManager;
5 | import android.graphics.SurfaceTexture;
6 | import android.opengl.EGL14;
7 | import android.opengl.GLES20;
8 | import android.opengl.GLES30;
9 | import android.os.Build;
10 | import android.os.Handler;
11 | import android.os.HandlerThread;
12 | import android.support.annotation.RequiresApi;
13 | import android.view.Surface;
14 |
15 | import javax.microedition.khronos.egl.EGL10;
16 | import javax.microedition.khronos.egl.EGLContext;
17 |
18 | public class GifPlayer {
19 |
20 | public interface OnGifListener {
21 | void start();
22 |
23 | void size(int width, int height);
24 |
25 | void update();
26 |
27 | void end();
28 | }
29 |
30 | public enum PlayState {
31 | IDLE, PREPARE, PLAYING, STOP
32 | }
33 |
34 | private int mTexture;
35 | private HandlerThread mHandlerThread;
36 | private Handler mHandler;
37 | private PlayState mPlayState;
38 | private long mGifPlayerPtr;
39 | private Surface mSurface;
40 | private SurfaceTexture mSurfaceTexture;
41 | private int mSTexture;
42 | private EglHelper mEglHelper;
43 | private OnGifListener mOnGifListener;
44 |
45 | public GifPlayer(int texture) {
46 | mTexture = texture;
47 | mEglHelper = new EglHelper();
48 | mGifPlayerPtr = native_create();
49 | mPlayState = PlayState.IDLE;
50 | mHandlerThread = new HandlerThread("GifPlayer");
51 | mHandlerThread.start();
52 | mHandler = new Handler(mHandlerThread.getLooper());
53 | mSTexture = FGLUtils.createTexture();
54 | mSurfaceTexture = new SurfaceTexture(mSTexture);
55 | mSurface = new Surface(mSurfaceTexture);
56 | EGL10 mEgl = (EGL10) EGLContext.getEGL();
57 | final EGLContext eglContext = mEgl.eglGetCurrentContext();
58 | mHandler.post(new Runnable() {
59 | @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
60 | @Override
61 | public void run() {
62 | mEglHelper.initEgl(eglContext, mSurface);
63 | mEglHelper.glBindThread();
64 | GLES20.glClearColor(1, 1, 1, 1);
65 | GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
66 | }
67 | });
68 | }
69 |
70 | public void setOnGifListener(OnGifListener onGifListener) {
71 | this.mOnGifListener = onGifListener;
72 | }
73 |
74 | public boolean assetPlay(Context context, String gifPath) {
75 | return play(false, context, gifPath);
76 | }
77 |
78 | public boolean assetPlay(boolean once, Context context, String gifPath) {
79 | return play(once, context, gifPath);
80 | }
81 |
82 | public boolean pause() {
83 | if (mPlayState == PlayState.PLAYING) {
84 | native_pause(mGifPlayerPtr);
85 | return true;
86 | }
87 | return false;
88 | }
89 |
90 | public boolean resume() {
91 | if (mPlayState == PlayState.PLAYING) {
92 | native_resume(mGifPlayerPtr);
93 | return true;
94 | }
95 | return false;
96 | }
97 |
98 | public boolean stop() {
99 | if (mPlayState != PlayState.IDLE) {
100 | mPlayState = PlayState.STOP;
101 | native_stop(mGifPlayerPtr);
102 | mHandler.post(new Runnable() {
103 | @Override
104 | public void run() {
105 | mPlayState = PlayState.IDLE;
106 | }
107 | });
108 | return true;
109 | }
110 | return false;
111 | }
112 |
113 | public void destroy() {
114 | native_stop(mGifPlayerPtr);
115 | mOnGifListener = null;
116 | mHandler.post(new Runnable() {
117 | @Override
118 | public void run() {
119 | native_release(mGifPlayerPtr);
120 | mGifPlayerPtr = 0;
121 | mHandlerThread.quit();
122 | mHandler = null;
123 | mHandlerThread = null;
124 | //
125 | mEglHelper.destroyEgl();
126 | mSurfaceTexture.release();
127 | mSurface.release();
128 | }
129 | });
130 | // try {
131 | // mHandlerThread.join();
132 | // } catch (InterruptedException e) {
133 | //// e.printStackTrace();
134 | // }
135 | }
136 |
137 | private boolean play(final boolean once, final Context context, final String gifPath) {
138 | if (mPlayState == PlayState.IDLE && mSurface != null) {
139 | mPlayState = PlayState.PREPARE;
140 | mHandler.post(new Runnable() {
141 | @Override
142 | public void run() {
143 | if (mOnGifListener != null) {
144 | mOnGifListener.start();
145 | }
146 | if (native_load(mGifPlayerPtr, context != null ? context.getResources().getAssets() : null, gifPath)) {
147 | mPlayState = PlayState.PLAYING;
148 | if (mOnGifListener != null) {
149 | mOnGifListener.size(native_get_width(mGifPlayerPtr), native_get_height(mGifPlayerPtr));
150 | }
151 | native_start(mGifPlayerPtr, once, mTexture, new Runnable() {
152 | @Override
153 | public void run() {
154 | // mEglHelper.swapBuffers();
155 | if (mOnGifListener != null) {
156 | mOnGifListener.update();
157 | }
158 | }
159 | });
160 | }
161 | mPlayState = PlayState.IDLE;
162 | if (mOnGifListener != null) {
163 | mOnGifListener.end();
164 | }
165 | }
166 | });
167 | } else {
168 | return false;
169 | }
170 | return true;
171 | }
172 |
173 | static {
174 | System.loadLibrary("gifplayer");
175 | }
176 |
177 | private native long native_create();
178 |
179 | private native boolean native_load(long ptr, AssetManager assetManager, String gifPath);
180 |
181 | private native void native_start(long ptr, boolean once, int texture, Runnable updateBitmap);
182 |
183 | private native int native_get_width(long ptr);
184 |
185 | private native int native_get_height(long ptr);
186 |
187 | private native void native_pause(long ptr);
188 |
189 | private native void native_resume(long ptr);
190 |
191 | private native void native_stop(long ptr);
192 |
193 | private native void native_release(long ptr);
194 |
195 | }
196 |
--------------------------------------------------------------------------------
/giflib/src/main/java/com/dming/testgif/ShaderHelper.java:
--------------------------------------------------------------------------------
1 | package com.dming.testgif;
2 |
3 | import android.content.Context;
4 | import android.opengl.GLES20;
5 |
6 | import java.io.IOException;
7 | import java.io.InputStream;
8 | import java.nio.ByteBuffer;
9 | import java.nio.ByteOrder;
10 | import java.nio.FloatBuffer;
11 | import java.nio.ShortBuffer;
12 |
13 | public class ShaderHelper {
14 |
15 | /**
16 | * 编译顶点着色器
17 | *
18 | * @param shaderCode 编译代码
19 | * @return 着色器对象ID
20 | */
21 | public static int compileVertexShader(String shaderCode) {
22 | return compileShader(GLES20.GL_VERTEX_SHADER, shaderCode);
23 | }
24 |
25 | /**
26 | * 编译片段着色器
27 | *
28 | * @param shaderCode 编译代码
29 | * @return 着色器对象ID
30 | */
31 | public static int compileFragmentShader(String shaderCode) {
32 | return compileShader(GLES20.GL_FRAGMENT_SHADER, shaderCode);
33 | }
34 |
35 | /**
36 | * 编译片段着色器
37 | *
38 | * @param type 着色器类型
39 | * @param shaderCode 编译代码
40 | * @return 着色器对象ID
41 | */
42 | private static int compileShader(int type, String shaderCode) {
43 | // 1.创建一个新的着色器对象
44 | final int shaderObjectId = GLES20.glCreateShader(type);
45 |
46 | // 2.获取创建状态
47 | if (shaderObjectId == 0) {
48 | // 在OpenGL中,都是通过整型值去作为OpenGL对象的引用。之后进行操作的时候都是将这个整型值传回给OpenGL进行操作。
49 | // 返回值0代表着创建对象失败。
50 | DLog.e("Could not create new shader.");
51 | return 0;
52 | }
53 |
54 | // 3.将着色器代码上传到着色器对象中
55 | GLES20.glShaderSource(shaderObjectId, shaderCode);
56 |
57 | // 4.编译着色器对象
58 | GLES20.glCompileShader(shaderObjectId);
59 |
60 | // 5.获取编译状态:OpenGL将想要获取的值放入长度为1的数组的首位
61 | final int[] compileStatus = new int[1];
62 | GLES20.glGetShaderiv(shaderObjectId, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
63 |
64 | // 打印编译的着色器信息
65 | // DLog.i( "Results of compiling source:" + "\n" + shaderCode + "\n:"
66 | // + GLES20.glGetShaderInfoLog(shaderObjectId));
67 |
68 | // 6.验证编译状态
69 | if (compileStatus[0] == 0) {
70 | // 如果编译失败,则删除创建的着色器对象
71 | GLES20.glDeleteShader(shaderObjectId);
72 | DLog.e("Compilation of shader failed.");
73 | // 7.返回着色器对象:失败,为0
74 | return 0;
75 | }
76 |
77 | // 7.返回着色器对象:成功,非0
78 | return shaderObjectId;
79 | }
80 |
81 | /**
82 | * 创建OpenGL程序:通过链接顶点着色器、片段着色器
83 | *
84 | * @param vertexShaderId 顶点着色器ID
85 | * @param fragmentShaderId 片段着色器ID
86 | * @return OpenGL程序ID
87 | */
88 | public static int linkProgram(int vertexShaderId, int fragmentShaderId) {
89 |
90 | // 1.创建一个OpenGL程序对象
91 | final int programObjectId = GLES20.glCreateProgram();
92 |
93 | // 2.获取创建状态
94 | if (programObjectId == 0) {
95 | DLog.e("Could not create new program");
96 | return 0;
97 | }
98 |
99 | // 3.将顶点着色器依附到OpenGL程序对象
100 | GLES20.glAttachShader(programObjectId, vertexShaderId);
101 | // 3.将片段着色器依附到OpenGL程序对象
102 | GLES20.glAttachShader(programObjectId, fragmentShaderId);
103 |
104 | // 4.将两个着色器链接到OpenGL程序对象
105 | GLES20.glLinkProgram(programObjectId);
106 |
107 | // 5.获取链接状态:OpenGL将想要获取的值放入长度为1的数组的首位
108 | final int[] linkStatus = new int[1];
109 | GLES20.glGetProgramiv(programObjectId, GLES20.GL_LINK_STATUS, linkStatus, 0);
110 |
111 | // 打印链接信息
112 | // DLog.i("Results of linking program:\n"
113 | // + GLES20.glGetProgramInfoLog(programObjectId));
114 |
115 | // 6.验证链接状态
116 | if (linkStatus[0] == 0) {
117 | // 链接失败则删除程序对象
118 | GLES20.glDeleteProgram(programObjectId);
119 | DLog.e("Linking of program failed.");
120 | // 7.返回程序对象:失败,为0
121 | return 0;
122 | }
123 | GLES20.glDeleteShader(vertexShaderId);
124 | GLES20.glDeleteShader(fragmentShaderId);
125 | // 7.返回程序对象:成功,非0
126 | return programObjectId;
127 | }
128 |
129 | /**
130 | * 验证OpenGL程序对象状态
131 | *
132 | * @param programObjectId OpenGL程序ID
133 | * @return 是否可用
134 | */
135 | private static boolean validateProgram(int programObjectId) {
136 | GLES20.glValidateProgram(programObjectId);
137 |
138 | final int[] validateStatus = new int[1];
139 | GLES20.glGetProgramiv(programObjectId, GLES20.GL_VALIDATE_STATUS, validateStatus, 0);
140 | DLog.i("Results of validating program: " + validateStatus[0]
141 | + "\nLog:" + GLES20.glGetProgramInfoLog(programObjectId));
142 |
143 | return validateStatus[0] != 0;
144 | }
145 |
146 | public static String readResource(Context context, int id) {
147 | InputStream inputStream = context.getResources().openRawResource(id);
148 | StringBuilder out = new StringBuilder();
149 | byte[] b = new byte[4096];
150 | try {
151 | for (int n; (n = inputStream.read(b)) != -1; ) {
152 | out.append(new String(b, 0, n));
153 | }
154 | } catch (IOException io) {
155 | }
156 | return out.toString();
157 | }
158 |
159 | /**
160 | * 创建OpenGL程序对象
161 | *
162 | * @param vertexShaderRes 顶点着色器代码
163 | * @param fragmentShaderRes 片段着色器代码
164 | */
165 | public static int loadProgram(Context context, int vertexShaderRes, int fragmentShaderRes) {
166 | final int vertexShaderId = ShaderHelper.compileVertexShader(readResource(context, vertexShaderRes));
167 | final int fragmentShaderId = ShaderHelper.compileFragmentShader(readResource(context, fragmentShaderRes));
168 | return ShaderHelper.linkProgram(vertexShaderId, fragmentShaderId);
169 | }
170 |
171 | public static FloatBuffer arrayToFloatBuffer(float[] fArray) {
172 | FloatBuffer fBuffer = ByteBuffer.allocateDirect(fArray.length * 4)
173 | .order(ByteOrder.nativeOrder())
174 | .asFloatBuffer()
175 | .put(fArray);
176 | fBuffer.position(0);
177 | return fBuffer;
178 | }
179 |
180 | public static ShortBuffer arrayToShortBuffer(short[] sArray) {
181 | ShortBuffer sBuffer = ByteBuffer.allocateDirect(sArray.length * 2)
182 | .order(ByteOrder.nativeOrder())
183 | .asShortBuffer()
184 | .put(sArray);
185 | sBuffer.position(0);
186 | return sBuffer;
187 | }
188 |
189 | }
190 |
--------------------------------------------------------------------------------
/giflib/src/main/res/raw/gif_process_frg.glsl:
--------------------------------------------------------------------------------
1 | precision mediump float;
2 | varying vec2 textureCoordinate;
3 | uniform sampler2D inputImageTexture;
4 |
5 | void main() {
6 | gl_FragColor = texture2D(inputImageTexture, textureCoordinate);
7 | }
--------------------------------------------------------------------------------
/giflib/src/main/res/raw/gif_process_ver.glsl:
--------------------------------------------------------------------------------
1 | //#version 100 es
2 |
3 | precision mediump float;
4 |
5 | attribute vec4 inputPosition;
6 | attribute vec4 inputTextureCoordinate;
7 | varying vec2 textureCoordinate;
8 | uniform mat4 inputMatrix;
9 | uniform mat4 uTexMatrix;
10 |
11 | void main() {
12 | gl_Position = inputPosition * inputMatrix;
13 | textureCoordinate = (uTexMatrix * inputTextureCoordinate).xy;
14 | }
--------------------------------------------------------------------------------
/giflib/src/test/java/com/dming/giflib/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.dming.giflib;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DMings/LearnOpengl/4f3c4d0974c29d8da6672a3acf4187e828f80a92/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sat Oct 05 10:02:23 CST 2019
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/mdSrc/demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DMings/LearnOpengl/4f3c4d0974c29d8da6672a3acf4187e828f80a92/mdSrc/demo.gif
--------------------------------------------------------------------------------
/mdSrc/nine_gl.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DMings/LearnOpengl/4f3c4d0974c29d8da6672a3acf4187e828f80a92/mdSrc/nine_gl.apk
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':giflib'
2 |
--------------------------------------------------------------------------------