├── old_version
├── README.md
├── ver_2016.7.21.11.18
│ ├── README.md
│ ├── core
│ │ └── src
│ │ │ ├── MyGdxGame0606.gwt.xml
│ │ │ └── com
│ │ │ └── mygdx
│ │ │ └── game0606
│ │ │ ├── DeviceCameraControl.java
│ │ │ ├── actor
│ │ │ └── FirstActor.java
│ │ │ ├── util
│ │ │ └── GetUrlImg.java
│ │ │ ├── Constant.java
│ │ │ └── MyGdxGame0606.java
│ └── Android
│ │ └── src
│ │ └── com
│ │ └── mygdx
│ │ └── game0606
│ │ └── android
│ │ ├── CameraSurface.java
│ │ ├── AndroidLauncher.java
│ │ └── AndroidDeviceCameraController.java
├── core
│ └── src
│ │ ├── MyGdxGame0606.gwt.xml
│ │ └── com
│ │ └── mygdx
│ │ └── game0606
│ │ ├── DeviceCameraControl.java
│ │ ├── actor
│ │ └── FirstActor.java
│ │ ├── util
│ │ └── GetUrlImg.java
│ │ ├── Constant.java
│ │ └── MyGdxGame0606.java
└── android
│ └── src
│ └── com
│ └── mygdx
│ └── game0606
│ └── android
│ ├── CameraSurface.java
│ ├── AndroidLauncher.java
│ └── AndroidDeviceCameraController.java
├── settings.gradle
├── readme_img
├── 1.jpg
├── 2.jpg
├── 3.png
└── 4.jpg
├── android
├── assets
│ ├── badlogic.jpg
│ └── data
│ │ ├── bg.png
│ │ ├── play.png
│ │ ├── cat_0.png
│ │ ├── cat_1.png
│ │ ├── cat_2.png
│ │ ├── cat_3.png
│ │ ├── start.png
│ │ └── takepictures.png
├── ic_launcher-web.png
├── res
│ ├── drawable-hdpi
│ │ └── ic_launcher.png
│ ├── drawable-mdpi
│ │ └── ic_launcher.png
│ ├── drawable-xhdpi
│ │ └── ic_launcher.png
│ ├── drawable-xxhdpi
│ │ └── ic_launcher.png
│ └── values
│ │ ├── strings.xml
│ │ └── styles.xml
├── project.properties
├── AndroidManifest.xml
├── proguard-project.txt
├── src
│ └── pri
│ │ └── weiqiang
│ │ └── camera
│ │ ├── CameraSurface.java
│ │ ├── AndroidLauncher.java
│ │ └── AndroidDeviceCameraController.java
└── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── core
├── build.gradle
└── src
│ └── pri
│ └── weiqiang
│ └── camera
│ ├── DeviceCameraControl.java
│ └── AndroidCamera.java
├── .gitignore
├── gradlew.bat
├── gradlew
└── README.md
/old_version/README.md:
--------------------------------------------------------------------------------
1 | 为调试代码,仅留备忘使用!
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include 'android', 'core'
--------------------------------------------------------------------------------
/old_version/ver_2016.7.21.11.18/README.md:
--------------------------------------------------------------------------------
1 | 实现两个按键,按下1,进行预览,按下2,进行聚焦拍摄
--------------------------------------------------------------------------------
/readme_img/1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/HEAD/readme_img/1.jpg
--------------------------------------------------------------------------------
/readme_img/2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/HEAD/readme_img/2.jpg
--------------------------------------------------------------------------------
/readme_img/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/HEAD/readme_img/3.png
--------------------------------------------------------------------------------
/readme_img/4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/HEAD/readme_img/4.jpg
--------------------------------------------------------------------------------
/android/assets/badlogic.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/HEAD/android/assets/badlogic.jpg
--------------------------------------------------------------------------------
/android/assets/data/bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/HEAD/android/assets/data/bg.png
--------------------------------------------------------------------------------
/android/assets/data/play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/HEAD/android/assets/data/play.png
--------------------------------------------------------------------------------
/android/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/HEAD/android/ic_launcher-web.png
--------------------------------------------------------------------------------
/android/assets/data/cat_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/HEAD/android/assets/data/cat_0.png
--------------------------------------------------------------------------------
/android/assets/data/cat_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/HEAD/android/assets/data/cat_1.png
--------------------------------------------------------------------------------
/android/assets/data/cat_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/HEAD/android/assets/data/cat_2.png
--------------------------------------------------------------------------------
/android/assets/data/cat_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/HEAD/android/assets/data/cat_3.png
--------------------------------------------------------------------------------
/android/assets/data/start.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/HEAD/android/assets/data/start.png
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.daemon=true
2 | org.gradle.jvmargs=-Xms128m -Xmx1500m
3 | org.gradle.configureondemand=true
4 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/android/assets/data/takepictures.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/HEAD/android/assets/data/takepictures.png
--------------------------------------------------------------------------------
/android/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/HEAD/android/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/HEAD/android/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/HEAD/android/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/54wall/LibgdxAndroidCamera/HEAD/android/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | AndroidCamera
5 |
6 |
7 |
--------------------------------------------------------------------------------
/core/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: "java"
2 |
3 | sourceCompatibility = 1.6
4 | [compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
5 |
6 | sourceSets.main.java.srcDirs = [ "src/" ]
7 |
8 |
9 | eclipse.project {
10 | name = appName + "-core"
11 | }
12 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sat Sep 21 13:08:26 CEST 2013
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=http\://services.gradle.org/distributions/gradle-2.10-all.zip
7 |
--------------------------------------------------------------------------------
/old_version/core/src/MyGdxGame0606.gwt.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/old_version/ver_2016.7.21.11.18/core/src/MyGdxGame0606.gwt.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/android/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/android/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-19
15 |
--------------------------------------------------------------------------------
/core/src/pri/weiqiang/camera/DeviceCameraControl.java:
--------------------------------------------------------------------------------
1 | package pri.weiqiang.camera;
2 |
3 | import com.badlogic.gdx.files.FileHandle;
4 | import com.badlogic.gdx.graphics.Pixmap;
5 |
6 | /**
7 | * @author 54wall
8 | * @date 创建时间:2016-7-14 下午12:38:29
9 | * @version 1.0
10 | */
11 | public interface DeviceCameraControl {
12 |
13 | // Synchronous interface
14 | void prepareCamera();
15 | void startPreview();
16 | void stopPreview();
17 | void takePicture();
18 | byte[] getPictureData();
19 | // Asynchronous interface - need when called from a non platform thread (GDXOpenGl thread)
20 | void startPreviewAsync();
21 | void stopPreviewAsync();
22 | byte[] takePictureAsync(long timeout);
23 | void saveAsJpeg(FileHandle jpgfile, Pixmap cameraPixmap);
24 | boolean isReady();
25 | void prepareCameraAsync();
26 | }
--------------------------------------------------------------------------------
/old_version/core/src/com/mygdx/game0606/DeviceCameraControl.java:
--------------------------------------------------------------------------------
1 | package com.mygdx.game0606;
2 |
3 | import com.badlogic.gdx.files.FileHandle;
4 | import com.badlogic.gdx.graphics.Pixmap;
5 |
6 | /**
7 | * @author 54wall
8 | * @date 创建时间:2016-7-14 下午12:38:29
9 | * @version 1.0
10 | */
11 | public interface DeviceCameraControl {
12 |
13 | // Synchronous interface
14 | void prepareCamera();
15 |
16 | void startPreview();
17 |
18 | void stopPreview();
19 |
20 | void takePicture();
21 |
22 | byte[] getPictureData();
23 |
24 | // Asynchronous interface - need when called from a non platform thread (GDX
25 | // OpenGl thread)
26 | void startPreviewAsync();
27 |
28 | void stopPreviewAsync();
29 |
30 | byte[] takePictureAsync(long timeout);
31 |
32 | void saveAsJpeg(FileHandle jpgfile, Pixmap cameraPixmap);
33 |
34 | boolean isReady();
35 |
36 | void prepareCameraAsync();
37 | }
--------------------------------------------------------------------------------
/old_version/ver_2016.7.21.11.18/core/src/com/mygdx/game0606/DeviceCameraControl.java:
--------------------------------------------------------------------------------
1 | package com.mygdx.game0606;
2 |
3 | import com.badlogic.gdx.files.FileHandle;
4 | import com.badlogic.gdx.graphics.Pixmap;
5 |
6 | /**
7 | * @author 54wall
8 | * @date 创建时间:2016-7-14 下午12:38:29
9 | * @version 1.0
10 | */
11 | public interface DeviceCameraControl {
12 |
13 | // Synchronous interface
14 | void prepareCamera();
15 |
16 | void startPreview();
17 |
18 | void stopPreview();
19 |
20 | void takePicture();
21 |
22 | byte[] getPictureData();
23 |
24 | // Asynchronous interface - need when called from a non platform thread (GDX
25 | // OpenGl thread)
26 | void startPreviewAsync();
27 |
28 | void stopPreviewAsync();
29 |
30 | byte[] takePictureAsync(long timeout);
31 |
32 | void saveAsJpeg(FileHandle jpgfile, Pixmap cameraPixmap);
33 |
34 | boolean isReady();
35 |
36 | void prepareCameraAsync();
37 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Java
2 |
3 | *.class
4 | *.war
5 | *.ear
6 | hs_err_pid*
7 |
8 | ## Robovm
9 | robovm-build/
10 |
11 | ## GWT
12 | war/
13 | html/war/gwt_bree/
14 | html/gwt-unitCache/
15 | .apt_generated/
16 | html/war/WEB-INF/deploy/
17 | html/war/WEB-INF/classes/
18 | .gwt/
19 | gwt-unitCache/
20 | www-test/
21 | .gwt-tmp/
22 |
23 | ## Android Studio and Intellij and Android in general
24 | android/libs/armeabi/
25 | android/libs/armeabi-v7a/
26 | android/libs/arm64-v8a/
27 | android/libs/x86/
28 | android/libs/x86_64/
29 | android/gen/
30 | .idea/
31 | *.ipr
32 | *.iws
33 | *.iml
34 | out/
35 | com_crashlytics_export_strings.xml
36 |
37 | ## Eclipse
38 | .classpath
39 | .project
40 | .metadata
41 | **/bin/
42 | tmp/
43 | *.tmp
44 | *.bak
45 | *.swp
46 | *~.nib
47 | local.properties
48 | .settings/
49 | .loadpath
50 | .externalToolBuilders/
51 | *.launch
52 |
53 | ## NetBeans
54 | **/nbproject/private/
55 | build/
56 | nbbuild/
57 | dist/
58 | nbdist/
59 | nbactions.xml
60 | nb-configuration.xml
61 |
62 | ## Gradle
63 |
64 | .gradle
65 | gradle-app.setting
66 | build/
67 |
68 | ## OS Specific
69 | .DS_Store
70 | Thumbs.db
71 |
--------------------------------------------------------------------------------
/old_version/core/src/com/mygdx/game0606/actor/FirstActor.java:
--------------------------------------------------------------------------------
1 | package com.mygdx.game0606.actor;
2 |
3 | /**
4 | * @author 54wall
5 | * @date 创建时间:2016-7-21 下午1:16:58
6 | * @version 1.0
7 | */
8 | import com.badlogic.gdx.Gdx;
9 | import com.badlogic.gdx.graphics.Texture;
10 | import com.badlogic.gdx.graphics.g2d.SpriteBatch;
11 | import com.badlogic.gdx.scenes.scene2d.Actor;
12 |
13 | public class FirstActor extends Actor {
14 | Texture texture;
15 |
16 | public void draw(SpriteBatch batch, float parentAlpha) {
17 | batch.draw(texture, this.getX(), this.getY());
18 | }
19 |
20 | public Actor hit(float x, float y) {
21 | if (x > 0 && y > 0 && this.getHeight() > y && this.getWidth() > x) {
22 | return this;
23 | } else {
24 | return null;
25 | }
26 | }
27 |
28 | public boolean touchDown(float x, float y, int pointer) {
29 | // TODO Auto-generated method stub
30 | return false;
31 | }
32 |
33 | public void touchDragged(float x, float y, int pointer) {
34 | // TODO Auto-generated method stub
35 | }
36 |
37 | public void touchUp(float x, float y, int pointer) {
38 | // TODO Auto-generated method stub
39 | }
40 |
41 | public FirstActor(String name) {
42 | super();
43 | texture = new Texture(Gdx.files.internal("data/james.png"));
44 | // this.height = texture.getHeight();
45 | // this.width = texture.getWidth();
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/old_version/ver_2016.7.21.11.18/core/src/com/mygdx/game0606/actor/FirstActor.java:
--------------------------------------------------------------------------------
1 | package com.mygdx.game0606.actor;
2 |
3 | /**
4 | * @author 54wall
5 | * @date 创建时间:2016-7-21 下午1:16:58
6 | * @version 1.0
7 | */
8 | import com.badlogic.gdx.Gdx;
9 | import com.badlogic.gdx.graphics.Texture;
10 | import com.badlogic.gdx.graphics.g2d.SpriteBatch;
11 | import com.badlogic.gdx.scenes.scene2d.Actor;
12 |
13 | public class FirstActor extends Actor {
14 | Texture texture;
15 |
16 | public void draw(SpriteBatch batch, float parentAlpha) {
17 | batch.draw(texture, this.getX(), this.getY());
18 | }
19 |
20 | public Actor hit(float x, float y) {
21 | if (x > 0 && y > 0 && this.getHeight() > y && this.getWidth() > x) {
22 | return this;
23 | } else {
24 | return null;
25 | }
26 | }
27 |
28 | public boolean touchDown(float x, float y, int pointer) {
29 | // TODO Auto-generated method stub
30 | return false;
31 | }
32 |
33 | public void touchDragged(float x, float y, int pointer) {
34 | // TODO Auto-generated method stub
35 | }
36 |
37 | public void touchUp(float x, float y, int pointer) {
38 | // TODO Auto-generated method stub
39 | }
40 |
41 | public FirstActor(String name) {
42 | super();
43 | texture = new Texture(Gdx.files.internal("data/james.png"));
44 | // this.height = texture.getHeight();
45 | // this.width = texture.getWidth();
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/android/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
24 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/android/proguard-project.txt:
--------------------------------------------------------------------------------
1 | # To enable ProGuard in your project, edit project.properties
2 | # to define the proguard.config property as described in that file.
3 | #
4 | # Add project specific ProGuard rules here.
5 | # By default, the flags in this file are appended to flags specified
6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt
7 | # You can edit the include path and order by changing the ProGuard
8 | # include property in project.properties.
9 | #
10 | # For more details, see
11 | # http://developer.android.com/guide/developing/tools/proguard.html
12 |
13 | # Add any project specific keep options here:
14 |
15 | # If your project uses WebView with JS, uncomment the following
16 | # and specify the fully qualified class name to the JavaScript interface
17 | # class:
18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19 | # public *;
20 | #}
21 |
22 | -verbose
23 |
24 | -dontwarn android.support.**
25 | -dontwarn com.badlogic.gdx.backends.android.AndroidFragmentApplication
26 | -dontwarn com.badlogic.gdx.utils.GdxBuild
27 | -dontwarn com.badlogic.gdx.physics.box2d.utils.Box2DBuild
28 | -dontwarn com.badlogic.gdx.jnigen.BuildTarget*
29 | -dontwarn com.badlogic.gdx.graphics.g2d.freetype.FreetypeBuild
30 |
31 | -keep class com.badlogic.gdx.controllers.android.AndroidControllers
32 |
33 | -keepclassmembers class com.badlogic.gdx.backends.android.AndroidInput* {
34 | (com.badlogic.gdx.Application, android.content.Context, java.lang.Object, com.badlogic.gdx.backends.android.AndroidApplicationConfiguration);
35 | }
36 |
37 | -keepclassmembers class com.badlogic.gdx.physics.box2d.World {
38 | boolean contactFilter(long, long);
39 | void beginContact(long);
40 | void endContact(long);
41 | void preSolve(long, long);
42 | void postSolve(long, long);
43 | boolean reportFixture(long);
44 | float reportRayFixture(long, float, float, float, float, float);
45 | }
46 |
--------------------------------------------------------------------------------
/android/src/pri/weiqiang/camera/CameraSurface.java:
--------------------------------------------------------------------------------
1 | package pri.weiqiang.camera;
2 |
3 | /**
4 | * @author 54wall
5 | * @date 创建时间:2016-7-14 上午11:44:40
6 | * @version 1.0
7 | */
8 |
9 | import java.io.IOException;
10 | import android.content.Context;
11 | import android.hardware.Camera;
12 | import android.os.Build;
13 | import android.view.SurfaceHolder;
14 | import android.view.SurfaceView;
15 |
16 | public class CameraSurface extends SurfaceView implements
17 | SurfaceHolder.Callback {
18 | private Camera camera;
19 |
20 | public CameraSurface(Context context) {
21 | super(context);
22 | // We're implementing the Callback interface and want to get notified
23 | // about certain surface events.
24 | getHolder().addCallback(this);
25 | // We're changing the surface to a PUSH surface, meaning we're receiving
26 | // all buffer data from another component - the camera, in this case.
27 | getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
28 | }
29 | public void surfaceCreated(SurfaceHolder holder) {
30 | // Once the surface is created, simply open a handle to the camera
31 | // hardware.
32 | // camera = Camera.open();
33 | camera = Camera.open(0);
34 | camera.setDisplayOrientation(90);
35 | }
36 |
37 | public void surfaceChanged(SurfaceHolder holder, int format, int width,
38 | int height) {
39 | // This method is called when the surface changes, e.g. when it's size
40 | // is set.
41 | // We use the opportunity to initialize the camera preview display
42 | // dimensions.
43 | Camera.Parameters p = camera.getParameters();
44 | // p.setPreviewSize(width, height);//old 会报 setParameters failed
45 | camera.setParameters(p);
46 |
47 | // We also assign the preview display to this surface...
48 | try {
49 | camera.setPreviewDisplay(holder);
50 | } catch (IOException e) {
51 | e.printStackTrace();
52 | }
53 | }
54 |
55 | public void surfaceDestroyed(SurfaceHolder holder) {
56 | // Once the surface gets destroyed, we stop the preview mode and release
57 | // the whole camera since we no longer need it.
58 | camera.stopPreview();
59 | camera.release();
60 | camera = null;
61 | }
62 |
63 | public Camera getCamera() {
64 | return camera;
65 | }
66 |
67 | }
--------------------------------------------------------------------------------
/old_version/ver_2016.7.21.11.18/Android/src/com/mygdx/game0606/android/CameraSurface.java:
--------------------------------------------------------------------------------
1 | package com.mygdx.game0606.android;
2 |
3 | /**
4 | * @author 54wall
5 | * @date 创建时间:2016-7-14 上午11:44:40
6 | * @version 1.0
7 | */
8 |
9 | import java.io.IOException;
10 | import android.content.Context;
11 | import android.hardware.Camera;
12 | import android.os.Build;
13 | import android.view.SurfaceHolder;
14 | import android.view.SurfaceView;
15 |
16 | public class CameraSurface extends SurfaceView implements
17 | SurfaceHolder.Callback {
18 | private Camera camera;
19 |
20 | public CameraSurface(Context context) {
21 | super(context);
22 | // We're implementing the Callback interface and want to get notified
23 | // about certain surface events.
24 | getHolder().addCallback(this);
25 | // We're changing the surface to a PUSH surface, meaning we're receiving
26 | // all buffer data from another component - the camera, in this case.
27 | getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
28 | }
29 | public void surfaceCreated(SurfaceHolder holder) {
30 | // Once the surface is created, simply open a handle to the camera
31 | // hardware.
32 | // camera = Camera.open();
33 | camera = Camera.open(0);
34 | camera.setDisplayOrientation(90);
35 | }
36 |
37 | public void surfaceChanged(SurfaceHolder holder, int format, int width,
38 | int height) {
39 | // This method is called when the surface changes, e.g. when it's size
40 | // is set.
41 | // We use the opportunity to initialize the camera preview display
42 | // dimensions.
43 | Camera.Parameters p = camera.getParameters();
44 | // p.setPreviewSize(width, height);//old 会报 setParameters failed
45 | camera.setParameters(p);
46 |
47 | // We also assign the preview display to this surface...
48 | try {
49 | camera.setPreviewDisplay(holder);
50 | } catch (IOException e) {
51 | e.printStackTrace();
52 | }
53 | }
54 |
55 | public void surfaceDestroyed(SurfaceHolder holder) {
56 | // Once the surface gets destroyed, we stop the preview mode and release
57 | // the whole camera since we no longer need it.
58 | camera.stopPreview();
59 | camera.release();
60 | camera = null;
61 | }
62 |
63 | public Camera getCamera() {
64 | return camera;
65 | }
66 |
67 | }
--------------------------------------------------------------------------------
/old_version/android/src/com/mygdx/game0606/android/CameraSurface.java:
--------------------------------------------------------------------------------
1 | package com.mygdx.game0606.android;
2 |
3 | /**
4 | * @author 54wall
5 | * @date 创建时间:2016-7-14 上午11:44:40
6 | * @version 1.0
7 | */
8 |
9 | import java.io.IOException;
10 |
11 | import android.annotation.TargetApi;
12 | import android.content.Context;
13 | import android.hardware.Camera;
14 | import android.os.Build;
15 | import android.view.SurfaceHolder;
16 | import android.view.SurfaceView;
17 |
18 | public class CameraSurface extends SurfaceView implements
19 | SurfaceHolder.Callback {
20 | private Camera camera;
21 |
22 | public CameraSurface(Context context) {
23 | super(context);
24 | // We're implementing the Callback interface and want to get notified
25 | // about certain surface events.
26 | getHolder().addCallback(this);
27 | // We're changing the surface to a PUSH surface, meaning we're receiving
28 | // all buffer data from another component - the camera, in this case.
29 | getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
30 | }
31 |
32 | @TargetApi(Build.VERSION_CODES.GINGERBREAD)
33 | public void surfaceCreated(SurfaceHolder holder) {
34 | // Once the surface is created, simply open a handle to the camera
35 | // hardware.
36 | // camera = Camera.open();//old
37 | camera = Camera.open(0);
38 | camera.setDisplayOrientation(90);
39 | }
40 |
41 | public void surfaceChanged(SurfaceHolder holder, int format, int width,
42 | int height) {
43 | // This method is called when the surface changes, e.g. when it's size
44 | // is set.
45 | // We use the opportunity to initialize the camera preview display
46 | // dimensions.
47 | Camera.Parameters p = camera.getParameters();
48 | // p.setPreviewSize(width, height);//old 会报 setParameters failed
49 | camera.setParameters(p);
50 |
51 | // We also assign the preview display to this surface...
52 | try {
53 | camera.setPreviewDisplay(holder);
54 | } catch (IOException e) {
55 | e.printStackTrace();
56 | }
57 | }
58 |
59 | public void surfaceDestroyed(SurfaceHolder holder) {
60 | // Once the surface gets destroyed, we stop the preview mode and release
61 | // the whole camera since we no longer need it.
62 | camera.stopPreview();
63 | camera.release();
64 | camera = null;
65 | }
66 |
67 | public Camera getCamera() {
68 | return camera;
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/android/src/pri/weiqiang/camera/AndroidLauncher.java:
--------------------------------------------------------------------------------
1 | package pri.weiqiang.camera;
2 |
3 | import android.os.Bundle;
4 |
5 | import com.badlogic.gdx.backends.android.AndroidApplication;
6 | import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;
7 | import pri.weiqiang.camera.DeviceCameraControl;
8 | import pri.weiqiang.camera.AndroidCamera;
9 |
10 | import android.content.pm.ActivityInfo;
11 | import android.graphics.PixelFormat;
12 | import android.view.SurfaceView;
13 |
14 | public class AndroidLauncher extends AndroidApplication {
15 | private int origWidth;
16 | private int origHeight;
17 | @Override
18 | public void onCreate(Bundle savedInstanceState) {
19 | super.onCreate(savedInstanceState);
20 | //强制竖屏
21 | setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);//通过程序改变屏
22 | AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration();
23 | //OpenGL ES 1.x support removed from libgdx(http://www.badlogicgames.com/wordpress/?p=3311)
24 | // cfg.useGL20 = false;//54wall old
25 | // we need to change the default pixel format - since it does not
26 | // include an alpha channel
27 | // we need the alpha channel so the camera preview will be seen behind
28 | // the GL scene
29 | cfg.r = 8;
30 | cfg.g = 8;
31 | cfg.b = 8;
32 | cfg.a = 8;
33 | DeviceCameraControl cameraControl = new AndroidDeviceCameraController(
34 | this);
35 | //拍照程序在AndroidDeviceCameraController,通过cameraControl传给MyGdxGame0606,进入LibGDX
36 | initialize(new AndroidCamera(cameraControl), cfg);
37 |
38 | if (graphics.getView() instanceof SurfaceView) {
39 | SurfaceView glView = (SurfaceView) graphics.getView();
40 | // force alpha channel - I'm not sure we need this as the GL surface
41 | // is already using alpha channel
42 | glView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
43 | }
44 | // we don't want the screen to turn off during the long image saving
45 | // process
46 | graphics.getView().setKeepScreenOn(true);
47 | // keep the original screen size
48 | origWidth = graphics.getWidth();
49 | origHeight = graphics.getHeight();
50 | }
51 |
52 | public void post(Runnable r) {
53 | handler.post(r);
54 | }
55 |
56 | public void setFixedSize(int width, int height) {
57 | if (graphics.getView() instanceof SurfaceView) {
58 | SurfaceView glView = (SurfaceView) graphics.getView();
59 | glView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
60 | glView.getHolder().setFixedSize(width, height);
61 | }
62 | }
63 |
64 | public void restoreFixedSize() {
65 | if (graphics.getView() instanceof SurfaceView) {
66 | SurfaceView glView = (SurfaceView) graphics.getView();
67 | glView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
68 | glView.getHolder().setFixedSize(origWidth, origHeight);
69 | }
70 | }
71 | }
--------------------------------------------------------------------------------
/old_version/android/src/com/mygdx/game0606/android/AndroidLauncher.java:
--------------------------------------------------------------------------------
1 | package com.mygdx.game0606.android;
2 |
3 | import android.os.Bundle;
4 |
5 | import com.badlogic.gdx.backends.android.AndroidApplication;
6 | import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;
7 | import com.mygdx.game0606.DeviceCameraControl;
8 | import com.mygdx.game0606.MyGdxGame0606;
9 |
10 | import android.content.pm.ActivityInfo;
11 | import android.graphics.PixelFormat;
12 | import android.view.SurfaceView;
13 |
14 | public class AndroidLauncher extends AndroidApplication {
15 | private int origWidth;
16 | private int origHeight;
17 | @Override
18 | public void onCreate(Bundle savedInstanceState) {
19 | super.onCreate(savedInstanceState);
20 | //强制竖屏
21 | setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);//通过程序改变屏
22 | AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration();
23 | //OpenGL ES 1.x support removed from libgdx(http://www.badlogicgames.com/wordpress/?p=3311)
24 | // cfg.useGL20 = false;//54wall old
25 | // we need to change the default pixel format - since it does not
26 | // include an alpha channel
27 | // we need the alpha channel so the camera preview will be seen behind
28 | // the GL scene
29 | cfg.r = 8;
30 | cfg.g = 8;
31 | cfg.b = 8;
32 | cfg.a = 8;
33 | DeviceCameraControl cameraControl = new AndroidDeviceCameraController(
34 | this);
35 | //拍照程序在AndroidDeviceCameraController,通过cameraControl传给MyGdxGame0606,进入LibGDX
36 | initialize(new MyGdxGame0606(cameraControl), cfg);
37 |
38 | if (graphics.getView() instanceof SurfaceView) {
39 | SurfaceView glView = (SurfaceView) graphics.getView();
40 | // force alpha channel - I'm not sure we need this as the GL surface
41 | // is already using alpha channel
42 | glView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
43 | }
44 | // we don't want the screen to turn off during the long image saving
45 | // process
46 | graphics.getView().setKeepScreenOn(true);
47 | // keep the original screen size
48 | origWidth = graphics.getWidth();
49 | origHeight = graphics.getHeight();
50 | }
51 |
52 | public void post(Runnable r) {
53 | handler.post(r);
54 | }
55 |
56 | public void setFixedSize(int width, int height) {
57 | if (graphics.getView() instanceof SurfaceView) {
58 | SurfaceView glView = (SurfaceView) graphics.getView();
59 | glView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
60 | glView.getHolder().setFixedSize(width, height);
61 | }
62 | }
63 |
64 | public void restoreFixedSize() {
65 | if (graphics.getView() instanceof SurfaceView) {
66 | SurfaceView glView = (SurfaceView) graphics.getView();
67 | glView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
68 | glView.getHolder().setFixedSize(origWidth, origHeight);
69 | }
70 | }
71 | }
--------------------------------------------------------------------------------
/old_version/ver_2016.7.21.11.18/Android/src/com/mygdx/game0606/android/AndroidLauncher.java:
--------------------------------------------------------------------------------
1 | package com.mygdx.game0606.android;
2 |
3 | import android.os.Bundle;
4 |
5 | import com.badlogic.gdx.backends.android.AndroidApplication;
6 | import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;
7 | import com.mygdx.game0606.DeviceCameraControl;
8 | import com.mygdx.game0606.MyGdxGame0606;
9 |
10 | import android.content.pm.ActivityInfo;
11 | import android.graphics.PixelFormat;
12 | import android.view.SurfaceView;
13 |
14 | public class AndroidLauncher extends AndroidApplication {
15 | private int origWidth;
16 | private int origHeight;
17 | @Override
18 | public void onCreate(Bundle savedInstanceState) {
19 | super.onCreate(savedInstanceState);
20 | //强制竖屏
21 | setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);//通过程序改变屏
22 | AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration();
23 | //OpenGL ES 1.x support removed from libgdx(http://www.badlogicgames.com/wordpress/?p=3311)
24 | // cfg.useGL20 = false;//54wall old
25 | // we need to change the default pixel format - since it does not
26 | // include an alpha channel
27 | // we need the alpha channel so the camera preview will be seen behind
28 | // the GL scene
29 | cfg.r = 8;
30 | cfg.g = 8;
31 | cfg.b = 8;
32 | cfg.a = 8;
33 | DeviceCameraControl cameraControl = new AndroidDeviceCameraController(
34 | this);
35 | //拍照程序在AndroidDeviceCameraController,通过cameraControl传给MyGdxGame0606,进入LibGDX
36 | initialize(new MyGdxGame0606(cameraControl), cfg);
37 |
38 | if (graphics.getView() instanceof SurfaceView) {
39 | SurfaceView glView = (SurfaceView) graphics.getView();
40 | // force alpha channel - I'm not sure we need this as the GL surface
41 | // is already using alpha channel
42 | glView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
43 | }
44 | // we don't want the screen to turn off during the long image saving
45 | // process
46 | graphics.getView().setKeepScreenOn(true);
47 | // keep the original screen size
48 | origWidth = graphics.getWidth();
49 | origHeight = graphics.getHeight();
50 | }
51 |
52 | public void post(Runnable r) {
53 | handler.post(r);
54 | }
55 |
56 | public void setFixedSize(int width, int height) {
57 | if (graphics.getView() instanceof SurfaceView) {
58 | SurfaceView glView = (SurfaceView) graphics.getView();
59 | glView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
60 | glView.getHolder().setFixedSize(width, height);
61 | }
62 | }
63 |
64 | public void restoreFixedSize() {
65 | if (graphics.getView() instanceof SurfaceView) {
66 | SurfaceView glView = (SurfaceView) graphics.getView();
67 | glView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
68 | glView.getHolder().setFixedSize(origWidth, origHeight);
69 | }
70 | }
71 | }
--------------------------------------------------------------------------------
/old_version/core/src/com/mygdx/game0606/util/GetUrlImg.java:
--------------------------------------------------------------------------------
1 | package com.mygdx.game0606.util;
2 |
3 | import java.io.ByteArrayOutputStream;
4 | import java.io.IOException;
5 | import java.io.InputStream;
6 | import java.net.MalformedURLException;
7 | import java.net.URL;
8 |
9 | import com.badlogic.gdx.Gdx;
10 | import com.badlogic.gdx.graphics.Pixmap;
11 | import com.badlogic.gdx.graphics.Pixmap.Format;
12 | import com.badlogic.gdx.graphics.Texture;
13 | import com.badlogic.gdx.graphics.g2d.TextureRegion;
14 | import com.badlogic.gdx.math.MathUtils;
15 |
16 | /**
17 | * @author 54wall
18 | * @date 创建时间:2016-7-21 下午3:51:09
19 | * @version 1.0
20 | * http://veikr.com/201203/libgdx_load_texture_network_async.html
21 | * libgdx中异步从网络加载图片
22 | */
23 | public class GetUrlImg {
24 |
25 | public void getImg() throws MalformedURLException, IOException {
26 | /* 从url读取byte[] */
27 | InputStream is = new URL("").openStream();
28 | ByteArrayOutputStream out = new ByteArrayOutputStream();
29 | int length = 0;
30 | byte[] bytes = new byte[1024];
31 | while ((length = is.read(bytes)) != -1) {
32 | out.write(bytes, 0, length);
33 | }
34 | is.close();
35 | out.flush();
36 | byte[] rtn = out.toByteArray();
37 |
38 | /* 使用byte[]生成一个pixmap */
39 | Pixmap pixmap = new Pixmap(bytes, 0, bytes.length);
40 |
41 | /* 将pixmap画到texture上 */
42 | int width = pixmap.getWidth();
43 | int height = pixmap.getHeight();
44 | int preferWidth = MathUtils.nextPowerOfTwo(width);
45 | int preferHeight = MathUtils.nextPowerOfTwo(height);
46 | Texture texture = new Texture(preferWidth, preferHeight,
47 | pixmap.getFormat());
48 | texture.draw(pixmap, 0, 0);
49 | pixmap.dispose();
50 | /* 构造textureRegion */
51 | TextureRegion region = new TextureRegion(texture, 0, 0, width, height);
52 | }
53 |
54 | public void name() {
55 | TextureRegion region = new TextureRegion(new Texture(1, 1,
56 | Format.RGBA8888));
57 | loadTextureRegionFromUrl(region, "http://sss.com/asdf.png");
58 | }
59 |
60 | public static void loadTextureRegionFromUrl(final TextureRegion region,
61 | final String url) {
62 | if (region == null) {
63 | throw new NullPointerException("region不能为空");
64 | }
65 | new Thread() {
66 | @Override
67 | public void run() {
68 | /* 还没有新建ReaderHelper */
69 | // final byte[] bytes = ReaderHelper.getBytesFromUrl(url);
70 | final byte[] bytes = null;
71 | System.out.println(url + " 图片获取成功:" + bytes.length);
72 | Gdx.app.postRunnable(new Runnable() {
73 | @Override
74 | public void run() {
75 | Pixmap pixmap = new Pixmap(bytes, 0, bytes.length);
76 | int width = pixmap.getWidth();
77 | int height = pixmap.getHeight();
78 | int preferWidth = MathUtils.nextPowerOfTwo(width);
79 | int preferHeight = MathUtils.nextPowerOfTwo(height);
80 | Texture texture = new Texture(preferWidth,
81 | preferHeight, pixmap.getFormat());
82 | texture.draw(pixmap, 0, 0);
83 | pixmap.dispose();
84 | region.setTexture(texture);
85 | region.setRegion(0, 0, width, height);
86 | System.out.println(region.getRegionWidth());
87 | System.out.println(region.getRegionHeight());
88 | System.out.println(region.getTexture().getHeight());
89 | }
90 | });
91 | };
92 | }.start();
93 | }
94 |
95 | }
96 |
--------------------------------------------------------------------------------
/old_version/ver_2016.7.21.11.18/core/src/com/mygdx/game0606/util/GetUrlImg.java:
--------------------------------------------------------------------------------
1 | package com.mygdx.game0606.util;
2 |
3 | import java.io.ByteArrayOutputStream;
4 | import java.io.IOException;
5 | import java.io.InputStream;
6 | import java.net.MalformedURLException;
7 | import java.net.URL;
8 |
9 | import com.badlogic.gdx.Gdx;
10 | import com.badlogic.gdx.graphics.Pixmap;
11 | import com.badlogic.gdx.graphics.Pixmap.Format;
12 | import com.badlogic.gdx.graphics.Texture;
13 | import com.badlogic.gdx.graphics.g2d.TextureRegion;
14 | import com.badlogic.gdx.math.MathUtils;
15 |
16 | /**
17 | * @author 54wall
18 | * @date 创建时间:2016-7-21 下午3:51:09
19 | * @version 1.0
20 | * http://veikr.com/201203/libgdx_load_texture_network_async.html
21 | * libgdx中异步从网络加载图片
22 | */
23 | public class GetUrlImg {
24 |
25 | public void getImg() throws MalformedURLException, IOException {
26 | /* 从url读取byte[] */
27 | InputStream is = new URL("").openStream();
28 | ByteArrayOutputStream out = new ByteArrayOutputStream();
29 | int length = 0;
30 | byte[] bytes = new byte[1024];
31 | while ((length = is.read(bytes)) != -1) {
32 | out.write(bytes, 0, length);
33 | }
34 | is.close();
35 | out.flush();
36 | byte[] rtn = out.toByteArray();
37 |
38 | /* 使用byte[]生成一个pixmap */
39 | Pixmap pixmap = new Pixmap(bytes, 0, bytes.length);
40 |
41 | /* 将pixmap画到texture上 */
42 | int width = pixmap.getWidth();
43 | int height = pixmap.getHeight();
44 | int preferWidth = MathUtils.nextPowerOfTwo(width);
45 | int preferHeight = MathUtils.nextPowerOfTwo(height);
46 | Texture texture = new Texture(preferWidth, preferHeight,
47 | pixmap.getFormat());
48 | texture.draw(pixmap, 0, 0);
49 | pixmap.dispose();
50 | /* 构造textureRegion */
51 | TextureRegion region = new TextureRegion(texture, 0, 0, width, height);
52 | }
53 |
54 | public void name() {
55 | TextureRegion region = new TextureRegion(new Texture(1, 1,
56 | Format.RGBA8888));
57 | loadTextureRegionFromUrl(region, "http://sss.com/asdf.png");
58 | }
59 |
60 | public static void loadTextureRegionFromUrl(final TextureRegion region,
61 | final String url) {
62 | if (region == null) {
63 | throw new NullPointerException("region不能为空");
64 | }
65 | new Thread() {
66 | @Override
67 | public void run() {
68 | /* 还没有新建ReaderHelper */
69 | // final byte[] bytes = ReaderHelper.getBytesFromUrl(url);
70 | final byte[] bytes = null;
71 | System.out.println(url + " 图片获取成功:" + bytes.length);
72 | Gdx.app.postRunnable(new Runnable() {
73 | @Override
74 | public void run() {
75 | Pixmap pixmap = new Pixmap(bytes, 0, bytes.length);
76 | int width = pixmap.getWidth();
77 | int height = pixmap.getHeight();
78 | int preferWidth = MathUtils.nextPowerOfTwo(width);
79 | int preferHeight = MathUtils.nextPowerOfTwo(height);
80 | Texture texture = new Texture(preferWidth,
81 | preferHeight, pixmap.getFormat());
82 | texture.draw(pixmap, 0, 0);
83 | pixmap.dispose();
84 | region.setTexture(texture);
85 | region.setRegion(0, 0, width, height);
86 | System.out.println(region.getRegionWidth());
87 | System.out.println(region.getRegionHeight());
88 | System.out.println(region.getTexture().getHeight());
89 | }
90 | });
91 | };
92 | }.start();
93 | }
94 |
95 | }
96 |
--------------------------------------------------------------------------------
/old_version/core/src/com/mygdx/game0606/Constant.java:
--------------------------------------------------------------------------------
1 | package com.mygdx.game0606;
2 |
3 | import com.badlogic.gdx.graphics.Color;
4 |
5 | /**
6 | * @author 54wall
7 | * @date 创建时间:2016-7-19 下午3:18:21
8 | * @version 1.0
9 | */
10 | public class Constant {
11 |
12 | public static final float vertexData[] = {
13 | 1.0f,
14 | 1.0f,
15 | 1.0f,
16 | Color.toFloatBits(255, 255, 255, 255),
17 | 0.0f,
18 | 0.0f, // quad/face 0/Vertex 0
19 | 0.0f,
20 | 1.0f,
21 | 1.0f,
22 | Color.toFloatBits(255, 255, 255, 255),
23 | 0.0f,
24 | 1.0f, // quad/face 0/Vertex 1
25 | 0.0f,
26 | 0.0f,
27 | 1.0f,
28 | Color.toFloatBits(255, 255, 255, 255),
29 | 1.0f,
30 | 1.0f, // quad/face 0/Vertex 2
31 | 1.0f,
32 | 0.0f,
33 | 1.0f,
34 | Color.toFloatBits(255, 255, 255, 255),
35 | 1.0f,
36 | 0.0f, // quad/face 0/Vertex 3
37 |
38 | 1.0f,
39 | 1.0f,
40 | 1.0f,
41 | Color.toFloatBits(255, 255, 255, 255),
42 | 1.0f,
43 | 1.0f, // quad/face 1/Vertex 4
44 | 1.0f,
45 | 0.0f,
46 | 1.0f,
47 | Color.toFloatBits(255, 255, 255, 255),
48 | 0.0f,
49 | 1.0f, // quad/face 1/Vertex 5
50 | 1.0f,
51 | 0.0f,
52 | 0.0f,
53 | Color.toFloatBits(255, 255, 255, 255),
54 | 0.0f,
55 | 0.0f, // quad/face 1/Vertex 6
56 | 1.0f,
57 | 1.0f,
58 | 0.0f,
59 | Color.toFloatBits(255, 255, 255, 255),
60 | 1.0f,
61 | 0.0f, // quad/face 1/Vertex 7
62 |
63 | 1.0f,
64 | 1.0f,
65 | 1.0f,
66 | Color.toFloatBits(255, 255, 255, 255),
67 | 0.0f,
68 | 0.0f, // quad/face 2/Vertex 8
69 | 1.0f,
70 | 1.0f,
71 | 0.0f,
72 | Color.toFloatBits(255, 255, 255, 255),
73 | 0.0f,
74 | 1.0f, // quad/face 2/Vertex 9
75 | 0.0f,
76 | 1.0f,
77 | 0.0f,
78 | Color.toFloatBits(255, 255, 255, 255),
79 | 1.0f,
80 | 1.0f, // quad/face 2/Vertex 10
81 | 0.0f,
82 | 1.0f,
83 | 1.0f,
84 | Color.toFloatBits(255, 255, 255, 255),
85 | 1.0f,
86 | 0.0f, // quad/face 2/Vertex 11
87 |
88 | 1.0f,
89 | 0.0f,
90 | 0.0f,
91 | Color.toFloatBits(255, 255, 255, 255),
92 | 1.0f,
93 | 1.0f, // quad/face 3/Vertex 12
94 | 0.0f,
95 | 0.0f,
96 | 0.0f,
97 | Color.toFloatBits(255, 255, 255, 255),
98 | 0.0f,
99 | 1.0f, // quad/face 3/Vertex 13
100 | 0.0f,
101 | 1.0f,
102 | 0.0f,
103 | Color.toFloatBits(255, 255, 255, 255),
104 | 0.0f,
105 | 0.0f, // quad/face 3/Vertex 14
106 | 1.0f,
107 | 1.0f,
108 | 0.0f,
109 | Color.toFloatBits(255, 255, 255, 255),
110 | 1.0f,
111 | 0.0f, // quad/face 3/Vertex 15
112 |
113 | 0.0f,
114 | 1.0f,
115 | 1.0f,
116 | Color.toFloatBits(255, 255, 255, 255),
117 | 1.0f,
118 | 1.0f, // quad/face 4/Vertex 16
119 | 0.0f,
120 | 1.0f,
121 | 0.0f,
122 | Color.toFloatBits(255, 255, 255, 255),
123 | 0.0f,
124 | 1.0f, // quad/face 4/Vertex 17
125 | 0.0f,
126 | 0.0f,
127 | 0.0f,
128 | Color.toFloatBits(255, 255, 255, 255),
129 | 0.0f,
130 | 0.0f, // quad/face 4/Vertex 18
131 | 0.0f,
132 | 0.0f,
133 | 1.0f,
134 | Color.toFloatBits(255, 255, 255, 255),
135 | 1.0f,
136 | 0.0f, // quad/face 4/Vertex 19
137 |
138 | 0.0f, 0.0f,
139 | 0.0f,
140 | Color.toFloatBits(255, 255, 255, 255),
141 | 1.0f,
142 | 1.0f, // quad/face 5/Vertex 20
143 | 1.0f, 0.0f, 0.0f,
144 | Color.toFloatBits(255, 255, 255, 255),
145 | 0.0f,
146 | 1.0f, // quad/face 5/Vertex 21
147 | 1.0f, 0.0f, 1.0f, Color.toFloatBits(255, 255, 255, 255),
148 | 0.0f,
149 | 0.0f, // quad/face 5/Vertex 22
150 | 0.0f, 0.0f, 1.0f, Color.toFloatBits(255, 255, 255, 255), 1.0f,
151 | 0.0f, // quad/face 5/Vertex 23
152 | };
153 | }
154 |
--------------------------------------------------------------------------------
/old_version/ver_2016.7.21.11.18/core/src/com/mygdx/game0606/Constant.java:
--------------------------------------------------------------------------------
1 | package com.mygdx.game0606;
2 |
3 | import com.badlogic.gdx.graphics.Color;
4 |
5 | /**
6 | * @author 54wall
7 | * @date 创建时间:2016-7-19 下午3:18:21
8 | * @version 1.0
9 | */
10 | public class Constant {
11 |
12 | public static final float vertexData[] = {
13 | 1.0f,
14 | 1.0f,
15 | 1.0f,
16 | Color.toFloatBits(255, 255, 255, 255),
17 | 0.0f,
18 | 0.0f, // quad/face 0/Vertex 0
19 | 0.0f,
20 | 1.0f,
21 | 1.0f,
22 | Color.toFloatBits(255, 255, 255, 255),
23 | 0.0f,
24 | 1.0f, // quad/face 0/Vertex 1
25 | 0.0f,
26 | 0.0f,
27 | 1.0f,
28 | Color.toFloatBits(255, 255, 255, 255),
29 | 1.0f,
30 | 1.0f, // quad/face 0/Vertex 2
31 | 1.0f,
32 | 0.0f,
33 | 1.0f,
34 | Color.toFloatBits(255, 255, 255, 255),
35 | 1.0f,
36 | 0.0f, // quad/face 0/Vertex 3
37 |
38 | 1.0f,
39 | 1.0f,
40 | 1.0f,
41 | Color.toFloatBits(255, 255, 255, 255),
42 | 1.0f,
43 | 1.0f, // quad/face 1/Vertex 4
44 | 1.0f,
45 | 0.0f,
46 | 1.0f,
47 | Color.toFloatBits(255, 255, 255, 255),
48 | 0.0f,
49 | 1.0f, // quad/face 1/Vertex 5
50 | 1.0f,
51 | 0.0f,
52 | 0.0f,
53 | Color.toFloatBits(255, 255, 255, 255),
54 | 0.0f,
55 | 0.0f, // quad/face 1/Vertex 6
56 | 1.0f,
57 | 1.0f,
58 | 0.0f,
59 | Color.toFloatBits(255, 255, 255, 255),
60 | 1.0f,
61 | 0.0f, // quad/face 1/Vertex 7
62 |
63 | 1.0f,
64 | 1.0f,
65 | 1.0f,
66 | Color.toFloatBits(255, 255, 255, 255),
67 | 0.0f,
68 | 0.0f, // quad/face 2/Vertex 8
69 | 1.0f,
70 | 1.0f,
71 | 0.0f,
72 | Color.toFloatBits(255, 255, 255, 255),
73 | 0.0f,
74 | 1.0f, // quad/face 2/Vertex 9
75 | 0.0f,
76 | 1.0f,
77 | 0.0f,
78 | Color.toFloatBits(255, 255, 255, 255),
79 | 1.0f,
80 | 1.0f, // quad/face 2/Vertex 10
81 | 0.0f,
82 | 1.0f,
83 | 1.0f,
84 | Color.toFloatBits(255, 255, 255, 255),
85 | 1.0f,
86 | 0.0f, // quad/face 2/Vertex 11
87 |
88 | 1.0f,
89 | 0.0f,
90 | 0.0f,
91 | Color.toFloatBits(255, 255, 255, 255),
92 | 1.0f,
93 | 1.0f, // quad/face 3/Vertex 12
94 | 0.0f,
95 | 0.0f,
96 | 0.0f,
97 | Color.toFloatBits(255, 255, 255, 255),
98 | 0.0f,
99 | 1.0f, // quad/face 3/Vertex 13
100 | 0.0f,
101 | 1.0f,
102 | 0.0f,
103 | Color.toFloatBits(255, 255, 255, 255),
104 | 0.0f,
105 | 0.0f, // quad/face 3/Vertex 14
106 | 1.0f,
107 | 1.0f,
108 | 0.0f,
109 | Color.toFloatBits(255, 255, 255, 255),
110 | 1.0f,
111 | 0.0f, // quad/face 3/Vertex 15
112 |
113 | 0.0f,
114 | 1.0f,
115 | 1.0f,
116 | Color.toFloatBits(255, 255, 255, 255),
117 | 1.0f,
118 | 1.0f, // quad/face 4/Vertex 16
119 | 0.0f,
120 | 1.0f,
121 | 0.0f,
122 | Color.toFloatBits(255, 255, 255, 255),
123 | 0.0f,
124 | 1.0f, // quad/face 4/Vertex 17
125 | 0.0f,
126 | 0.0f,
127 | 0.0f,
128 | Color.toFloatBits(255, 255, 255, 255),
129 | 0.0f,
130 | 0.0f, // quad/face 4/Vertex 18
131 | 0.0f,
132 | 0.0f,
133 | 1.0f,
134 | Color.toFloatBits(255, 255, 255, 255),
135 | 1.0f,
136 | 0.0f, // quad/face 4/Vertex 19
137 |
138 | 0.0f, 0.0f,
139 | 0.0f,
140 | Color.toFloatBits(255, 255, 255, 255),
141 | 1.0f,
142 | 1.0f, // quad/face 5/Vertex 20
143 | 1.0f, 0.0f, 0.0f,
144 | Color.toFloatBits(255, 255, 255, 255),
145 | 0.0f,
146 | 1.0f, // quad/face 5/Vertex 21
147 | 1.0f, 0.0f, 1.0f, Color.toFloatBits(255, 255, 255, 255),
148 | 0.0f,
149 | 0.0f, // quad/face 5/Vertex 22
150 | 0.0f, 0.0f, 1.0f, Color.toFloatBits(255, 255, 255, 255), 1.0f,
151 | 0.0f, // quad/face 5/Vertex 23
152 | };
153 | }
154 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | android {
2 | buildToolsVersion "23.0.1"
3 | compileSdkVersion 20
4 | sourceSets {
5 | main {
6 | manifest.srcFile 'AndroidManifest.xml'
7 | java.srcDirs = ['src']
8 | aidl.srcDirs = ['src']
9 | renderscript.srcDirs = ['src']
10 | res.srcDirs = ['res']
11 | assets.srcDirs = ['assets']
12 | jniLibs.srcDirs = ['libs']
13 | }
14 |
15 | instrumentTest.setRoot('tests')
16 | }
17 | defaultConfig {
18 | applicationId "pri.weiqiang.camera"
19 | minSdkVersion 8
20 | targetSdkVersion 20
21 | }
22 | }
23 |
24 |
25 | // called every time gradle gets executed, takes the native dependencies of
26 | // the natives configuration, and extracts them to the proper libs/ folders
27 | // so they get packed with the APK.
28 | task copyAndroidNatives() {
29 | file("libs/armeabi/").mkdirs();
30 | file("libs/armeabi-v7a/").mkdirs();
31 | file("libs/arm64-v8a/").mkdirs();
32 | file("libs/x86_64/").mkdirs();
33 | file("libs/x86/").mkdirs();
34 |
35 | configurations.natives.files.each { jar ->
36 | def outputDir = null
37 | if(jar.name.endsWith("natives-arm64-v8a.jar")) outputDir = file("libs/arm64-v8a")
38 | if(jar.name.endsWith("natives-armeabi-v7a.jar")) outputDir = file("libs/armeabi-v7a")
39 | if(jar.name.endsWith("natives-armeabi.jar")) outputDir = file("libs/armeabi")
40 | if(jar.name.endsWith("natives-x86_64.jar")) outputDir = file("libs/x86_64")
41 | if(jar.name.endsWith("natives-x86.jar")) outputDir = file("libs/x86")
42 | if(outputDir != null) {
43 | copy {
44 | from zipTree(jar)
45 | into outputDir
46 | include "*.so"
47 | }
48 | }
49 | }
50 | }
51 |
52 | task run(type: Exec) {
53 | def path
54 | def localProperties = project.file("../local.properties")
55 | if (localProperties.exists()) {
56 | Properties properties = new Properties()
57 | localProperties.withInputStream { instr ->
58 | properties.load(instr)
59 | }
60 | def sdkDir = properties.getProperty('sdk.dir')
61 | if (sdkDir) {
62 | path = sdkDir
63 | } else {
64 | path = "$System.env.ANDROID_HOME"
65 | }
66 | } else {
67 | path = "$System.env.ANDROID_HOME"
68 | }
69 |
70 | def adb = path + "/platform-tools/adb"
71 | commandLine "$adb", 'shell', 'am', 'start', '-n', 'pri.weiqiang.camera/pri.weiqiang.camera.AndroidLauncher'
72 | }
73 |
74 | // sets up the Android Eclipse project, using the old Ant based build.
75 | eclipse {
76 | // need to specify Java source sets explicitly, SpringSource Gradle Eclipse plugin
77 | // ignores any nodes added in classpath.file.withXml
78 | sourceSets {
79 | main {
80 | java.srcDirs "src", 'gen'
81 | }
82 | }
83 |
84 | jdt {
85 | sourceCompatibility = 1.6
86 | targetCompatibility = 1.6
87 | }
88 |
89 | classpath {
90 | plusConfigurations += [ project.configurations.compile ]
91 | containers 'com.android.ide.eclipse.adt.ANDROID_FRAMEWORK', 'com.android.ide.eclipse.adt.LIBRARIES'
92 | }
93 |
94 | project {
95 | name = appName + "-android"
96 | natures 'com.android.ide.eclipse.adt.AndroidNature'
97 | buildCommands.clear();
98 | buildCommand "com.android.ide.eclipse.adt.ResourceManagerBuilder"
99 | buildCommand "com.android.ide.eclipse.adt.PreCompilerBuilder"
100 | buildCommand "org.eclipse.jdt.core.javabuilder"
101 | buildCommand "com.android.ide.eclipse.adt.ApkBuilder"
102 | }
103 | }
104 |
105 | // sets up the Android Idea project, using the old Ant based build.
106 | idea {
107 | module {
108 | sourceDirs += file("src");
109 | scopes = [ COMPILE: [plus:[project.configurations.compile]]]
110 |
111 | iml {
112 | withXml {
113 | def node = it.asNode()
114 | def builder = NodeBuilder.newInstance();
115 | builder.current = node;
116 | builder.component(name: "FacetManager") {
117 | facet(type: "android", name: "Android") {
118 | configuration {
119 | option(name: "UPDATE_PROPERTY_FILES", value:"true")
120 | }
121 | }
122 | }
123 | }
124 | }
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
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 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/android/src/pri/weiqiang/camera/AndroidDeviceCameraController.java:
--------------------------------------------------------------------------------
1 | package pri.weiqiang.camera;
2 |
3 | import java.io.FileNotFoundException;
4 | import java.io.FileOutputStream;
5 | import java.io.IOException;
6 | import java.util.List;
7 | import com.badlogic.gdx.files.FileHandle;
8 | import com.badlogic.gdx.graphics.Pixmap;
9 | import pri.weiqiang.camera.DeviceCameraControl;
10 |
11 |
12 | import android.content.Context;
13 | import android.graphics.Bitmap;
14 | import android.graphics.Bitmap.CompressFormat;
15 | import android.hardware.Camera;
16 | import android.hardware.Camera.PictureCallback;
17 | import android.hardware.Camera.ShutterCallback;
18 | import android.view.ViewGroup;
19 | import android.view.ViewParent;
20 | import android.widget.FrameLayout;
21 |
22 | public class AndroidDeviceCameraController implements DeviceCameraControl,
23 | Camera.PictureCallback, Camera.AutoFocusCallback {
24 |
25 | private static final int ONE_SECOND_IN_MILI = 1000;
26 | private final AndroidLauncher activity;
27 | private CameraSurface cameraSurface;
28 | private byte[] pictureData;
29 | private Context context;
30 |
31 | public AndroidDeviceCameraController(AndroidLauncher activity) {
32 | this.activity = activity;
33 | }
34 |
35 | @Override
36 | public synchronized void prepareCamera() {
37 | // activity.setFixedSize(960, 640);//new
38 | // activity.setFixedSize(480, 320);//54wall
39 | if (cameraSurface == null) {
40 | cameraSurface = new CameraSurface(activity);
41 | }
42 | //可以控制摄像头预览窗口大小
43 | // activity.addContentView(cameraSurface, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
44 | // activity.addContentView(cameraSurface, new LayoutParams(960, 640));
45 | /*http://blog.csdn.net/drrlalala/article/details/38332017*/
46 | FrameLayout.LayoutParams params = new FrameLayout.LayoutParams
47 | (680,680);
48 | //设置顶部,左边布局
49 | // params.gravity=Gravity.CENTER_HORIZONTAL|Gravity.RIGHT;
50 | // params.gravity=Gravity.LEFT|Gravity.RIGHT;
51 | params.rightMargin=150;//可以通过设置rightMargin控制组件的实际位置
52 | params.leftMargin=200;//可以通过设置rightMargin控制组件的实际位置
53 | params.topMargin=100;
54 | activity.addContentView(cameraSurface, params);
55 |
56 |
57 | }
58 |
59 | @Override
60 | public synchronized void startPreview() {
61 | // ...and start previewing. From now on, the camera keeps pushing preview images to the surface.
62 | if (cameraSurface != null && cameraSurface.getCamera() != null) {
63 | cameraSurface.getCamera().startPreview();
64 | }
65 | }
66 |
67 | @Override
68 | public synchronized void stopPreview() {
69 | // stop previewing.
70 | if (cameraSurface != null) {
71 | ViewParent parentView = cameraSurface.getParent();
72 | if (parentView instanceof ViewGroup) {
73 | ViewGroup viewGroup = (ViewGroup) parentView;
74 | viewGroup.removeView(cameraSurface);
75 | }
76 | if (cameraSurface.getCamera() != null) {
77 | cameraSurface.getCamera().stopPreview();
78 | }
79 | }
80 | activity.restoreFixedSize();
81 | }
82 |
83 | public void setCameraParametersForPicture(Camera camera) {
84 | // Before we take the picture - we make sure all camera parameters are
85 | // as we like them
86 | // Use max resolution and auto focus
87 | Camera.Parameters p = camera.getParameters();
88 | List supportedSizes = p.getSupportedPictureSizes();
89 | int maxSupportedWidth = -1;
90 | int maxSupportedHeight = -1;
91 | for (Camera.Size size : supportedSizes) {
92 | if (size.width > maxSupportedWidth) {
93 | maxSupportedWidth = size.width;
94 | maxSupportedHeight = size.height;
95 | }
96 | }
97 | p.setPictureSize(maxSupportedWidth, maxSupportedHeight);
98 | p.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
99 | camera.setParameters(p);
100 | }
101 |
102 | @Override
103 | public synchronized void takePicture() {
104 | // the user request to take a picture - start the process by requesting
105 | // focus
106 | setCameraParametersForPicture(cameraSurface.getCamera());
107 | cameraSurface.getCamera().autoFocus(this);
108 | }
109 |
110 | @Override
111 | public synchronized void onAutoFocus(boolean success, Camera camera) {
112 | // Focus process finished, we now have focus (or not)
113 | if (success) {
114 | if (camera != null) {
115 | camera.stopPreview();
116 | /*android6.0下边都是不推荐的了,具体找下相应替代语句*/
117 | // camera.takePicture(null, null, null, this);//old
118 | // camera.takePicture(null, null, null);//54wall
119 | /*增加三个回调函数后,可以进行拍照,并且成功保存*/
120 | // We now have focus take the actual picture
121 | camera.takePicture(shutterCallback, rawPictureCallback, jpegPictureCallback);//54wall
122 | /*54wall:末尾增加重新开始预览就可以继续预览图像了:http://www.xuebuyuan.com/1982434.html */
123 | camera.startPreview();
124 |
125 | }
126 | }
127 | }
128 |
129 |
130 |
131 |
132 | ShutterCallback shutterCallback = new ShutterCallback() {
133 | @Override
134 | public void onShutter() {
135 | }
136 | };
137 |
138 | PictureCallback rawPictureCallback = new PictureCallback() {
139 | @Override
140 | public void onPictureTaken(byte[] arg0, Camera arg1) {
141 |
142 | }
143 | };
144 |
145 | PictureCallback jpegPictureCallback = new PictureCallback() {
146 | @Override
147 | public void onPictureTaken(byte[] arg0, Camera arg1) {
148 | /*可以在Android项目中中生成图片*/
149 | // String fileName = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
150 | // .toString()
151 | // + File.separator
152 | // + "PicTest_" + System.currentTimeMillis() + ".jpg";
153 | // File file = new File(fileName);
154 | // if (!file.getParentFile().exists()) {
155 | // file.getParentFile().mkdir();
156 | // }
157 | //
158 | // try {
159 | // BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
160 | // bos.write(arg0);
161 | // bos.flush();
162 | // bos.close();
163 | //
164 | // } catch (Exception e) {
165 | //
166 | // }
167 | /*54wall:因为在libgdx合成图像时,发现pictureData=null*/
168 | pictureData=arg0;
169 |
170 | };
171 | };
172 |
173 | @Override
174 | public synchronized void onPictureTaken(byte[] pictureData, Camera camera) {
175 | // We got the picture data - keep it
176 | this.pictureData = pictureData;
177 | }
178 |
179 | @Override
180 | public synchronized byte[] getPictureData() {
181 | // Give to picture data to whom ever requested it
182 | return pictureData;
183 | }
184 |
185 | @Override
186 | public void prepareCameraAsync() {
187 | Runnable r = new Runnable() {
188 | public void run() {
189 | prepareCamera();
190 | }
191 | };
192 | activity.post(r);
193 | }
194 |
195 | @Override
196 | public synchronized void startPreviewAsync() {
197 | Runnable r = new Runnable() {
198 | public void run() {
199 | startPreview();
200 | }
201 | };
202 | activity.post(r);
203 | }
204 |
205 | @Override
206 | public synchronized void stopPreviewAsync() {
207 | Runnable r = new Runnable() {
208 | public void run() {
209 | stopPreview();
210 | }
211 | };
212 | activity.post(r);
213 | }
214 |
215 | @Override
216 | public synchronized byte[] takePictureAsync(long timeout) {
217 | timeout *= ONE_SECOND_IN_MILI;
218 | /*pictureData会报错*/
219 | // pictureData = null;//old
220 | Runnable r = new Runnable() {
221 | public void run() {
222 | takePicture();
223 | }
224 | };
225 | activity.post(r);
226 | while (pictureData == null && timeout > 0) {
227 | try {
228 | Thread.sleep(ONE_SECOND_IN_MILI);
229 | timeout -= ONE_SECOND_IN_MILI;
230 | } catch (InterruptedException e) {
231 | // TODO Auto-generated catch block
232 | e.printStackTrace();
233 | }
234 | }
235 | if (pictureData == null) {
236 | cameraSurface.getCamera().cancelAutoFocus();
237 | }
238 | return pictureData;
239 | }
240 |
241 |
242 |
243 | /*在LibGDX中,图片以pixmap为存在格式,所以Android与LibGDX进行交互,必须有saveAsJpeg*/
244 | @Override
245 | public void saveAsJpeg(FileHandle jpgfile, Pixmap pixmap) {
246 | FileOutputStream fos;
247 | int x = 0, y = 0;
248 | int xl = 0, yl = 0;
249 | try {
250 | Bitmap bmp = Bitmap.createBitmap(pixmap.getWidth(),
251 | pixmap.getHeight(), Bitmap.Config.ARGB_8888);
252 | // we need to switch between LibGDX RGBA format to Android ARGB
253 | // format
254 | for (x = 0, xl = pixmap.getWidth(); x < xl; x++) {
255 | for (y = 0, yl = pixmap.getHeight(); y < yl; y++) {
256 | int color = pixmap.getPixel(x, y);
257 | // RGBA => ARGB
258 | int RGB = color >> 8;
259 | int A = (color & 0x000000ff) << 24;
260 | int ARGB = A | RGB;
261 | bmp.setPixel(x, y, ARGB);
262 | }
263 | }
264 | fos = new FileOutputStream(jpgfile.file());
265 | bmp.compress(CompressFormat.JPEG, 90, fos);
266 | fos.close();
267 | } catch (FileNotFoundException e) {
268 | e.printStackTrace();
269 | } catch (IOException e) {
270 | e.printStackTrace();
271 | } catch (IllegalArgumentException e) {
272 | e.printStackTrace();
273 | }
274 | }
275 |
276 | @Override
277 | public boolean isReady() {
278 | if (cameraSurface != null && cameraSurface.getCamera() != null) {
279 | return true;
280 | }
281 | return false;
282 | }
283 | }
284 |
--------------------------------------------------------------------------------
/old_version/ver_2016.7.21.11.18/Android/src/com/mygdx/game0606/android/AndroidDeviceCameraController.java:
--------------------------------------------------------------------------------
1 | package com.mygdx.game0606.android;
2 |
3 | /**
4 | * @author 54wall
5 | * @date 创建时间:2016-7-14 上午11:45:41
6 | * @version 1.0
7 | */
8 | import java.io.BufferedOutputStream;
9 | import java.io.File;
10 | import java.io.FileNotFoundException;
11 | import java.io.FileOutputStream;
12 | import java.io.IOException;
13 | import java.util.List;
14 | import com.badlogic.gdx.files.FileHandle;
15 | import com.badlogic.gdx.graphics.Pixmap;
16 | import com.mygdx.game0606.DeviceCameraControl;
17 |
18 |
19 | import android.content.Context;
20 | import android.graphics.Bitmap;
21 | import android.graphics.Bitmap.CompressFormat;
22 | import android.hardware.Camera;
23 | import android.hardware.Camera.PictureCallback;
24 | import android.hardware.Camera.ShutterCallback;
25 | import android.os.Environment;
26 | import android.text.Layout;
27 | import android.view.Gravity;
28 | import android.view.ViewGroup;
29 | import android.view.ViewParent;
30 | import android.view.ViewGroup.LayoutParams;
31 | import android.widget.Button;
32 | import android.widget.FrameLayout;
33 | import android.widget.RelativeLayout;
34 | import android.widget.Toast;
35 |
36 | public class AndroidDeviceCameraController implements DeviceCameraControl,
37 | Camera.PictureCallback, Camera.AutoFocusCallback {
38 |
39 | private static final int ONE_SECOND_IN_MILI = 1000;
40 | private final AndroidLauncher activity;
41 | private CameraSurface cameraSurface;
42 | private byte[] pictureData;
43 | private Context context;
44 |
45 | public AndroidDeviceCameraController(AndroidLauncher activity) {
46 | this.activity = activity;
47 | }
48 |
49 | @Override
50 | public synchronized void prepareCamera() {
51 | // activity.setFixedSize(960, 640);//new
52 | // activity.setFixedSize(480, 320);//54wall
53 | if (cameraSurface == null) {
54 | cameraSurface = new CameraSurface(activity);
55 | }
56 | /*可以控制摄像头预览窗口大小*/
57 | // activity.addContentView(cameraSurface, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
58 | /*activity.addContentView只能有一个否则报错:
59 | * java.lang.IllegalStateException: The specified child already has a parent.
60 | * You must call removeView() on the child's parent first.
61 | * 这也是在core代码中libgdx只能在render中调用AndroidDeviceCameraController中开启相机的原因*/
62 | // activity.addContentView(cameraSurface, new LayoutParams(960, 640));
63 | /*http://blog.csdn.net/drrlalala/article/details/38332017*/
64 | FrameLayout.LayoutParams params = new FrameLayout.LayoutParams
65 | (680,680);
66 | //设置顶部,左边布局
67 | // params.gravity=Gravity.CENTER_HORIZONTAL|Gravity.RIGHT;
68 | // params.gravity=Gravity.LEFT|Gravity.RIGHT;
69 | params.rightMargin=150;//可以通过设置rightMargin控制组件的实际位置
70 | params.leftMargin=200;//可以通过设置rightMargin控制组件的实际位置
71 | params.topMargin=100;
72 | activity.addContentView(cameraSurface, params);
73 |
74 |
75 | }
76 |
77 | @Override
78 | public synchronized void startPreview() {
79 | // ...and start previewing. From now on, the camera keeps pushing preview images to the surface.
80 | if (cameraSurface != null && cameraSurface.getCamera() != null) {
81 | cameraSurface.getCamera().startPreview();
82 | }
83 | }
84 |
85 | @Override
86 | public synchronized void stopPreview() {
87 | // stop previewing.
88 | if (cameraSurface != null) {
89 | ViewParent parentView = cameraSurface.getParent();
90 | if (parentView instanceof ViewGroup) {
91 | ViewGroup viewGroup = (ViewGroup) parentView;
92 | viewGroup.removeView(cameraSurface);
93 | }
94 | if (cameraSurface.getCamera() != null) {
95 | cameraSurface.getCamera().stopPreview();
96 | }
97 | }
98 | activity.restoreFixedSize();
99 | }
100 |
101 | public void setCameraParametersForPicture(Camera camera) {
102 | // Before we take the picture - we make sure all camera parameters are
103 | // as we like them
104 | // Use max resolution and auto focus
105 | Camera.Parameters p = camera.getParameters();
106 | List supportedSizes = p.getSupportedPictureSizes();
107 | int maxSupportedWidth = -1;
108 | int maxSupportedHeight = -1;
109 | for (Camera.Size size : supportedSizes) {
110 | if (size.width > maxSupportedWidth) {
111 | maxSupportedWidth = size.width;
112 | maxSupportedHeight = size.height;
113 | }
114 | }
115 | p.setPictureSize(maxSupportedWidth, maxSupportedHeight);
116 | p.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
117 | camera.setParameters(p);
118 | }
119 |
120 | @Override
121 | public synchronized void takePicture() {
122 | // the user request to take a picture - start the process by requesting
123 | // focus
124 | setCameraParametersForPicture(cameraSurface.getCamera());
125 | cameraSurface.getCamera().autoFocus(this);
126 | }
127 |
128 | @Override
129 | public synchronized void onAutoFocus(boolean success, Camera camera) {
130 | // Focus process finished, we now have focus (or not)
131 | if (success) {
132 | if (camera != null) {
133 | camera.stopPreview();
134 | /*android6.0下边都是不推荐的了,具体找下相应替代语句*/
135 | // camera.takePicture(null, null, null, this);//old
136 | // camera.takePicture(null, null, null);//54wall
137 | /*增加三个回调函数后,可以进行拍照,并且成功保存*/
138 | // We now have focus take the actual picture
139 | camera.takePicture(shutterCallback, rawPictureCallback, jpegPictureCallback);//54wall
140 | /*54wall:末尾增加重新开始预览就可以继续预览图像了:http://www.xuebuyuan.com/1982434.html */
141 | camera.startPreview();
142 |
143 | }
144 | }
145 | }
146 |
147 |
148 |
149 |
150 | ShutterCallback shutterCallback = new ShutterCallback() {
151 | @Override
152 | public void onShutter() {
153 | }
154 | };
155 |
156 | PictureCallback rawPictureCallback = new PictureCallback() {
157 | @Override
158 | public void onPictureTaken(byte[] arg0, Camera arg1) {
159 |
160 | }
161 | };
162 |
163 | PictureCallback jpegPictureCallback = new PictureCallback() {
164 | @Override
165 | public void onPictureTaken(byte[] arg0, Camera arg1) {
166 | /*可以在Android项目中中生成图片*/
167 | // String fileName = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
168 | // .toString()
169 | // + File.separator
170 | // + "PicTest_" + System.currentTimeMillis() + ".jpg";
171 | // File file = new File(fileName);
172 | // if (!file.getParentFile().exists()) {
173 | // file.getParentFile().mkdir();
174 | // }
175 | //
176 | // try {
177 | // BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
178 | // bos.write(arg0);
179 | // bos.flush();
180 | // bos.close();
181 | //
182 | // } catch (Exception e) {
183 | //
184 | // }
185 | /*54wall:因为在libgdx合成图像时,发现pictureData=null*/
186 | pictureData=arg0;
187 |
188 | };
189 | };
190 |
191 | @Override
192 | public synchronized void onPictureTaken(byte[] pictureData, Camera camera) {
193 | // We got the picture data - keep it
194 | this.pictureData = pictureData;
195 | }
196 |
197 | @Override
198 | public synchronized byte[] getPictureData() {
199 | // Give to picture data to whom ever requested it
200 | return pictureData;
201 | }
202 |
203 | @Override
204 | public void prepareCameraAsync() {
205 | Runnable r = new Runnable() {
206 | public void run() {
207 | prepareCamera();
208 | }
209 | };
210 | activity.post(r);
211 | }
212 |
213 | @Override
214 | public synchronized void startPreviewAsync() {
215 | Runnable r = new Runnable() {
216 | public void run() {
217 | startPreview();
218 | }
219 | };
220 | activity.post(r);
221 | }
222 |
223 | @Override
224 | public synchronized void stopPreviewAsync() {
225 | Runnable r = new Runnable() {
226 | public void run() {
227 | stopPreview();
228 | }
229 | };
230 | activity.post(r);
231 | }
232 |
233 | @Override
234 | public synchronized byte[] takePictureAsync(long timeout) {
235 | timeout *= ONE_SECOND_IN_MILI;
236 | /*pictureData会报错*/
237 | // pictureData = null;//old
238 | Runnable r = new Runnable() {
239 | public void run() {
240 | takePicture();
241 | }
242 | };
243 | activity.post(r);
244 | while (pictureData == null && timeout > 0) {
245 | try {
246 | Thread.sleep(ONE_SECOND_IN_MILI);
247 | timeout -= ONE_SECOND_IN_MILI;
248 | } catch (InterruptedException e) {
249 | // TODO Auto-generated catch block
250 | e.printStackTrace();
251 | }
252 | }
253 | if (pictureData == null) {
254 | cameraSurface.getCamera().cancelAutoFocus();
255 | }
256 | return pictureData;
257 | }
258 |
259 |
260 |
261 | /*在LibGDX中,图片以pixmap为存在格式,所以Android与LibGDX进行交互,必须有saveAsJpeg*/
262 | @Override
263 | public void saveAsJpeg(FileHandle jpgfile, Pixmap pixmap) {
264 | FileOutputStream fos;
265 | int x = 0, y = 0;
266 | int xl = 0, yl = 0;
267 | try {
268 | Bitmap bmp = Bitmap.createBitmap(pixmap.getWidth(),
269 | pixmap.getHeight(), Bitmap.Config.ARGB_8888);
270 | // we need to switch between LibGDX RGBA format to Android ARGB
271 | // format
272 | for (x = 0, xl = pixmap.getWidth(); x < xl; x++) {
273 | for (y = 0, yl = pixmap.getHeight(); y < yl; y++) {
274 | int color = pixmap.getPixel(x, y);
275 | // RGBA => ARGB
276 | int RGB = color >> 8;
277 | int A = (color & 0x000000ff) << 24;
278 | int ARGB = A | RGB;
279 | bmp.setPixel(x, y, ARGB);
280 | }
281 | }
282 | fos = new FileOutputStream(jpgfile.file());
283 | bmp.compress(CompressFormat.JPEG, 90, fos);
284 | fos.close();
285 | } catch (FileNotFoundException e) {
286 | e.printStackTrace();
287 | } catch (IOException e) {
288 | e.printStackTrace();
289 | } catch (IllegalArgumentException e) {
290 | e.printStackTrace();
291 | }
292 | }
293 |
294 | @Override
295 | public boolean isReady() {
296 | if (cameraSurface != null && cameraSurface.getCamera() != null) {
297 | return true;
298 | }
299 | return false;
300 | }
301 | }
302 |
--------------------------------------------------------------------------------
/old_version/android/src/com/mygdx/game0606/android/AndroidDeviceCameraController.java:
--------------------------------------------------------------------------------
1 | package com.mygdx.game0606.android;
2 |
3 | /**
4 | * @author 54wall
5 | * @date 创建时间:2016-7-14 上午11:45:41
6 | * @version 1.0
7 | */
8 | import java.io.BufferedOutputStream;
9 | import java.io.File;
10 | import java.io.FileNotFoundException;
11 | import java.io.FileOutputStream;
12 | import java.io.IOException;
13 | import java.util.List;
14 | import com.badlogic.gdx.files.FileHandle;
15 | import com.badlogic.gdx.graphics.Pixmap;
16 | import com.mygdx.game0606.DeviceCameraControl;
17 |
18 |
19 | import android.content.Context;
20 | import android.graphics.Bitmap;
21 | import android.graphics.Bitmap.CompressFormat;
22 | import android.hardware.Camera;
23 | import android.hardware.Camera.PictureCallback;
24 | import android.hardware.Camera.ShutterCallback;
25 | import android.os.Environment;
26 | import android.text.Layout;
27 | import android.view.Gravity;
28 | import android.view.ViewGroup;
29 | import android.view.ViewParent;
30 | import android.view.ViewGroup.LayoutParams;
31 | import android.widget.Button;
32 | import android.widget.FrameLayout;
33 | import android.widget.RelativeLayout;
34 | import android.widget.Toast;
35 |
36 | public class AndroidDeviceCameraController implements DeviceCameraControl,
37 | Camera.PictureCallback, Camera.AutoFocusCallback {
38 |
39 | private static final int ONE_SECOND_IN_MILI = 1000;
40 | private final AndroidLauncher activity;
41 | private CameraSurface cameraSurface;
42 | private byte[] pictureData;
43 | private Context context;
44 |
45 | public AndroidDeviceCameraController(AndroidLauncher activity) {
46 | this.activity = activity;
47 | }
48 |
49 | @Override
50 | public synchronized void prepareCamera() {
51 | // activity.setFixedSize(960, 640);//new
52 | // activity.setFixedSize(480, 320);//54wall
53 | if (cameraSurface == null) {
54 | cameraSurface = new CameraSurface(activity);
55 | }
56 | /*可以控制摄像头预览窗口大小*/
57 | // activity.addContentView(cameraSurface, new LayoutParams(
58 | // LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
59 | /*activity.addContentView只能有一个否则报错:
60 | * java.lang.IllegalStateException: The specified child already has a parent.
61 | * You must call removeView() on the child's parent first.
62 | * 这也是在core代码中libgdx只能在render中调用AndroidDeviceCameraController中开启相机的原因*/
63 | // activity.addContentView(cameraSurface, new LayoutParams(
64 | // 960, 640));
65 |
66 |
67 |
68 | /*http://blog.csdn.net/drrlalala/article/details/38332017*/
69 | FrameLayout.LayoutParams params = new FrameLayout.LayoutParams
70 | (680,680);
71 | //设置顶部,左边布局
72 | // params.gravity=Gravity.CENTER_HORIZONTAL|Gravity.RIGHT;
73 | // params.gravity=Gravity.LEFT|Gravity.RIGHT;
74 | params.rightMargin=150;//可以通过设置rightMargin控制组件的实际位置
75 | params.leftMargin=200;//可以通过设置rightMargin控制组件的实际位置
76 | params.topMargin=100;
77 | activity.addContentView(cameraSurface, params);
78 |
79 |
80 | }
81 |
82 | @Override
83 | public synchronized void startPreview() {
84 | // ...and start previewing. From now on, the camera keeps pushing preview images to the surface.
85 | if (cameraSurface != null && cameraSurface.getCamera() != null) {
86 | cameraSurface.getCamera().startPreview();
87 | }
88 | }
89 |
90 | @Override
91 | public synchronized void stopPreview() {
92 | // stop previewing.
93 | if (cameraSurface != null) {
94 | ViewParent parentView = cameraSurface.getParent();
95 | if (parentView instanceof ViewGroup) {
96 | ViewGroup viewGroup = (ViewGroup) parentView;
97 | viewGroup.removeView(cameraSurface);
98 | }
99 | if (cameraSurface.getCamera() != null) {
100 | cameraSurface.getCamera().stopPreview();
101 | }
102 | }
103 | activity.restoreFixedSize();
104 | }
105 |
106 | public void setCameraParametersForPicture(Camera camera) {
107 | // Before we take the picture - we make sure all camera parameters are
108 | // as we like them
109 | // Use max resolution and auto focus
110 | Camera.Parameters p = camera.getParameters();
111 | List supportedSizes = p.getSupportedPictureSizes();
112 | int maxSupportedWidth = -1;
113 | int maxSupportedHeight = -1;
114 | for (Camera.Size size : supportedSizes) {
115 | if (size.width > maxSupportedWidth) {
116 | maxSupportedWidth = size.width;
117 | maxSupportedHeight = size.height;
118 | }
119 | }
120 | p.setPictureSize(maxSupportedWidth, maxSupportedHeight);
121 | p.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
122 | camera.setParameters(p);
123 | }
124 |
125 | @Override
126 | public synchronized void takePicture() {
127 | // the user request to take a picture - start the process by requesting
128 | // focus
129 | setCameraParametersForPicture(cameraSurface.getCamera());
130 | cameraSurface.getCamera().autoFocus(this);
131 | }
132 |
133 | @Override
134 | public synchronized void onAutoFocus(boolean success, Camera camera) {
135 | // Focus process finished, we now have focus (or not)
136 | if (success) {
137 | if (camera != null) {
138 | camera.stopPreview();
139 | // We now have focus take the actual picture
140 | /*android6.0下边都是不推荐的了,具体找下相应替代语句*/
141 | // camera.takePicture(null, null, null, this);//old
142 | // camera.takePicture(null, null, null);//54wall new
143 | /*增加三个回调函数后,可以进行拍照,并且成功保存*/
144 | camera.takePicture(shutterCallback, rawPictureCallback, jpegPictureCallback);//54wall new
145 | /*54wall:末尾增加重新开始预览就可以继续预览图像了:http://www.xuebuyuan.com/1982434.html */
146 | camera.startPreview();
147 |
148 | }
149 | }
150 | }
151 |
152 |
153 |
154 |
155 | ShutterCallback shutterCallback = new ShutterCallback() {
156 | @Override
157 | public void onShutter() {
158 | }
159 | };
160 |
161 | PictureCallback rawPictureCallback = new PictureCallback() {
162 | @Override
163 | public void onPictureTaken(byte[] arg0, Camera arg1) {
164 |
165 | }
166 | };
167 |
168 | PictureCallback jpegPictureCallback = new PictureCallback() {
169 | @Override
170 | public void onPictureTaken(byte[] arg0, Camera arg1) {
171 | /*可以在Android中生成图片,也可以先LibGDX这篇教程一样,在core代码中生成图片,利用*/
172 | // String fileName = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
173 | // .toString()
174 | // + File.separator
175 | // + "PicTest_" + System.currentTimeMillis() + ".jpg";
176 | // File file = new File(fileName);
177 | // if (!file.getParentFile().exists()) {
178 | // file.getParentFile().mkdir();
179 | // }
180 | //
181 | // try {
182 | // BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
183 | // bos.write(arg0);
184 | // bos.flush();
185 | // bos.close();
186 | //
187 | // } catch (Exception e) {
188 | //
189 | // }
190 | /*54wall:因为在libgdx合成图像时,发现pictureData=null*/
191 | pictureData=arg0;
192 |
193 | };
194 | };
195 |
196 | @Override
197 | public synchronized void onPictureTaken(byte[] pictureData, Camera camera) {
198 | // We got the picture data - keep it
199 | this.pictureData = pictureData;
200 | }
201 |
202 | @Override
203 | public synchronized byte[] getPictureData() {
204 | // Give to picture data to whom ever requested it
205 | return pictureData;
206 | }
207 |
208 | @Override
209 | public void prepareCameraAsync() {
210 | Runnable r = new Runnable() {
211 | public void run() {
212 | prepareCamera();
213 | }
214 | };
215 | activity.post(r);
216 | }
217 |
218 | @Override
219 | public synchronized void startPreviewAsync() {
220 | Runnable r = new Runnable() {
221 | public void run() {
222 | startPreview();
223 | }
224 | };
225 | activity.post(r);
226 | }
227 |
228 | @Override
229 | public synchronized void stopPreviewAsync() {
230 | Runnable r = new Runnable() {
231 | public void run() {
232 | stopPreview();
233 | }
234 | };
235 | activity.post(r);
236 | }
237 |
238 | @Override
239 | public synchronized byte[] takePictureAsync(long timeout) {
240 | timeout *= ONE_SECOND_IN_MILI;
241 | /*pictureData会报错*/
242 | // pictureData = null;//old
243 | Runnable r = new Runnable() {
244 | public void run() {
245 | takePicture();
246 | }
247 | };
248 | activity.post(r);
249 | while (pictureData == null && timeout > 0) {
250 | try {
251 | Thread.sleep(ONE_SECOND_IN_MILI);
252 | timeout -= ONE_SECOND_IN_MILI;
253 | } catch (InterruptedException e) {
254 | // TODO Auto-generated catch block
255 | e.printStackTrace();
256 | }
257 | }
258 | if (pictureData == null) {
259 | cameraSurface.getCamera().cancelAutoFocus();
260 | }
261 | return pictureData;
262 | }
263 |
264 |
265 |
266 | /*在LibGDX中,图片以pixmap为存在格式,所以Android与LibGDX进行交互,必须有saveAsJpeg*/
267 | @Override
268 | public void saveAsJpeg(FileHandle jpgfile, Pixmap pixmap) {
269 | FileOutputStream fos;
270 | int x = 0, y = 0;
271 | int xl = 0, yl = 0;
272 | try {
273 | Bitmap bmp = Bitmap.createBitmap(pixmap.getWidth(),
274 | pixmap.getHeight(), Bitmap.Config.ARGB_8888);
275 | // we need to switch between LibGDX RGBA format to Android ARGB
276 | // format
277 | for (x = 0, xl = pixmap.getWidth(); x < xl; x++) {
278 | for (y = 0, yl = pixmap.getHeight(); y < yl; y++) {
279 | int color = pixmap.getPixel(x, y);
280 | // RGBA => ARGB
281 | int RGB = color >> 8;
282 | int A = (color & 0x000000ff) << 24;
283 | int ARGB = A | RGB;
284 | bmp.setPixel(x, y, ARGB);
285 | }
286 | }
287 | fos = new FileOutputStream(jpgfile.file());
288 | bmp.compress(CompressFormat.JPEG, 90, fos);
289 | fos.close();
290 | } catch (FileNotFoundException e) {
291 | e.printStackTrace();
292 | } catch (IOException e) {
293 | e.printStackTrace();
294 | } catch (IllegalArgumentException e) {
295 | e.printStackTrace();
296 | }
297 | }
298 |
299 | @Override
300 | public boolean isReady() {
301 | if (cameraSurface != null && cameraSurface.getCamera() != null) {
302 | return true;
303 | }
304 | return false;
305 | }
306 | }
307 |
--------------------------------------------------------------------------------
/core/src/pri/weiqiang/camera/AndroidCamera.java:
--------------------------------------------------------------------------------
1 | package pri.weiqiang.camera;
2 |
3 |
4 | import java.nio.ByteBuffer;
5 | import java.text.SimpleDateFormat;
6 | import com.badlogic.gdx.Application;
7 | import com.badlogic.gdx.ApplicationListener;
8 | import com.badlogic.gdx.Gdx;
9 | import com.badlogic.gdx.files.FileHandle;
10 | import com.badlogic.gdx.graphics.GL20;//oldGL20
11 | import com.badlogic.gdx.graphics.PerspectiveCamera;
12 | import com.badlogic.gdx.graphics.Pixmap;
13 | import com.badlogic.gdx.graphics.Texture;
14 | import com.badlogic.gdx.graphics.Texture.TextureFilter;
15 | import com.badlogic.gdx.graphics.Pixmap.Filter;
16 | import com.badlogic.gdx.graphics.Pixmap.Format;
17 | import com.badlogic.gdx.graphics.g2d.SpriteBatch;
18 | import com.badlogic.gdx.graphics.g2d.TextureRegion;
19 | import com.badlogic.gdx.scenes.scene2d.Actor;
20 | import com.badlogic.gdx.scenes.scene2d.InputEvent;
21 | import com.badlogic.gdx.scenes.scene2d.Stage;
22 | import com.badlogic.gdx.scenes.scene2d.ui.Button;
23 | import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
24 | import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
25 | import com.badlogic.gdx.utils.viewport.StretchViewport;
26 |
27 | public class AndroidCamera implements ApplicationListener {
28 | /* http://blog.csdn.net/xietansheng/article/details/50187861 */
29 | private Stage stage;// 舞台
30 | private Texture actorTexture;
31 | private Texture move_1_Texture;
32 | private Texture move_2_Texture;
33 | private Texture upTexture;
34 | private Texture downTexture;
35 | private Button button;
36 | private Button button_1;
37 | private Button button_move;
38 | // 视口世界的宽高统使用 480 * 800, 并统一使用伸展视口(StretchViewport)
39 | public static final float WORLD_WIDTH = 480;
40 | public static final float WORLD_HEIGHT = 800;
41 | public SpriteBatch batch;
42 | public Texture texture_demo;
43 | private SimpleDateFormat sDateFormat = new SimpleDateFormat(
44 | "yyyy-MM-dd hh:mm:ss");
45 | private String date = sDateFormat.format(new java.util.Date());
46 | public enum Mode {
47 | normal, prepare, preview, takePicture, waitForPictureReady,
48 | }
49 | public int state_normal = 0;
50 | public int state_prepare = 1;
51 | private Texture texture;
52 | private PerspectiveCamera camera;
53 | private Mode mode = Mode.normal;
54 | private final DeviceCameraControl deviceCameraControl;
55 | private long time_1;
56 | private long time_2;
57 | private Actor firstActor;
58 | /*
59 | * 通过this.deviceCameraControl=
60 | * cameraControl获取Android端摄像头然后后续所有的deviceCameraControl实际调用的都是Android的东西
61 | */
62 | public AndroidCamera(DeviceCameraControl cameraControl) {
63 | this.deviceCameraControl = cameraControl;
64 | }
65 |
66 | @Override
67 | public void create() {
68 | /* http://blog.csdn.net/xietansheng/article/details/50187861 */
69 | // 设置日志输出级别
70 | Gdx.app.setLogLevel(Application.LOG_DEBUG);
71 | // 使用伸展视口(StretchViewport)创建舞台
72 | stage = new Stage(new StretchViewport(WORLD_WIDTH, WORLD_HEIGHT));
73 | // 将输入处理设置到舞台(必须设置, 否则点击按钮没效果)
74 | Gdx.input.setInputProcessor(stage);
75 | firstActor = new Actor();
76 | firstActor.setHeight(150);
77 | firstActor.setWidth(150);
78 | firstActor.setPosition(150, 150);
79 | move_1_Texture = new Texture(Gdx.files.internal("data/play.png"));
80 | move_2_Texture = new Texture(Gdx.files.internal("data/start.png"));
81 | actorTexture = new Texture(Gdx.files.internal("data/cat_0.png"));
82 | upTexture = new Texture(Gdx.files.internal("data/start.png"));
83 | downTexture = new Texture(Gdx.files.internal("data/takepictures.png"));
84 | //创建 ButtonStyle
85 | Button.ButtonStyle style_move = new Button.ButtonStyle();
86 | Button.ButtonStyle style = new Button.ButtonStyle();
87 | style_move.up=new TextureRegionDrawable(new TextureRegion(move_1_Texture));
88 | style_move.down=new TextureRegionDrawable(new TextureRegion(move_2_Texture));
89 | style.up = new TextureRegionDrawable(new TextureRegion(upTexture));
90 | style.down = new TextureRegionDrawable(new TextureRegion(downTexture));
91 | button_move = new Button(style_move);
92 | // 设置按钮的位置
93 | button_move.setPosition(150, 300);
94 | // 给按钮添加点击监听器
95 | button_move.addListener(actor_move);
96 | button = new Button(style);
97 | // 设置按钮的位置
98 | button.setPosition(50, 300);
99 | // 给按钮添加点击监听器
100 | button.addListener(preview_on);
101 | button_1 = new Button(style);
102 | // 设置按钮的位置
103 | button_1.setPosition(300, 300);
104 | // 给按钮添加点击监听器
105 | button_1.addListener(preview_on_1);
106 | //添加 button 到舞台
107 | stage.addActor(button);
108 | stage.addActor(button_1);
109 | stage.addActor(button_move);
110 | stage.addActor(firstActor);
111 | batch = new SpriteBatch();
112 | // Load the Libgdx splash screen texture
113 | texture = new Texture(Gdx.files.internal("data/bg.png"));
114 | texture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
115 | // Create the OpenGL Camera,这里指的是视角,正交视角与设备摄像头完全不是一个东西
116 | camera = new PerspectiveCamera(67.0f, 2.0f * Gdx.graphics.getWidth()
117 | / Gdx.graphics.getHeight(), 2.0f);
118 | camera.far = 100.0f;
119 | camera.near = 0.1f;
120 | camera.position.set(2.0f, 2.0f, 2.0f);
121 | camera.lookAt(0.0f, 0.0f, 0.0f);
122 |
123 | }
124 |
125 | /* 手动释放资源 */
126 | @Override
127 | public void dispose() {
128 | /* 对应button,应用退出时释放资源 */
129 | if (upTexture != null) {
130 | upTexture.dispose();
131 | }
132 | if (downTexture != null) {
133 | downTexture.dispose();
134 | }
135 | if (stage != null) {
136 | stage.dispose();
137 | }
138 | batch.dispose();
139 | texture.dispose();
140 | texture = null;
141 | }
142 |
143 | @Override
144 | public void render() {
145 | // Gdx.gl20.glClearColor(0.0f, 0f, 0.0f, 0.0f);//黑
146 | // Gdx.gl.glClearColor(1, 1, 1, 1);//背景为白色
147 | Gdx.gl.glClearColor(0.57f, 0.40f, 0.55f, 1.0f);// 紫色
148 | Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);// 清屏
149 | render_preview();
150 |
151 | }
152 |
153 |
154 | public void render_preview() {
155 | /* 我已经将preview变为takePicture状态移动到click中,实现先预览再拍照,这样便于理解相机的运行步骤 */
156 | Gdx.gl20.glHint(GL20.GL_GENERATE_MIPMAP_HINT, GL20.GL_NICEST);
157 | if (mode == Mode.takePicture) {
158 | Gdx.gl20.glClearColor(0f, 0.0f, 0.0f, 0.0f);
159 | if (deviceCameraControl != null) {
160 | deviceCameraControl.takePicture();
161 | }
162 | mode = Mode.waitForPictureReady;
163 | } else if (mode == Mode.waitForPictureReady) {
164 | Gdx.gl20.glClearColor(0.0f, 0f, 0.0f, 0.0f);
165 | } else if (mode == Mode.prepare) {
166 | Gdx.gl20.glClearColor(0.0f, 0.0f, 0f, 0.6f);
167 | if (deviceCameraControl != null) {
168 | if (deviceCameraControl.isReady()) {
169 | deviceCameraControl.startPreviewAsync();
170 | mode = Mode.preview;
171 | }
172 | }
173 | } else if (mode == Mode.preview) {
174 | Gdx.gl20.glClearColor(0.0f, 0.0f, 0.0f, 0f);
175 | } else {
176 | /* mode = normal */
177 | Gdx.gl20.glClearColor(0.0f, 0.0f, 0.6f, 1.0f);
178 |
179 | }
180 | Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
181 | /* 下边放到texture.bind();时效果一致 */
182 | batch.begin();
183 | stage.act(); // 更新舞台逻辑
184 | batch.draw(texture, 0, 0, 3f*texture.getWidth(), 3f*texture.getHeight());
185 | Gdx.app.log("", String.valueOf(texture.getWidth()));
186 | //先绘制的就先出现,所以演员在texture上边,而不是被覆盖
187 | //batch.draw(actorTexture, firstActor.getX(), firstActor.getY());//原大小
188 | batch.draw(actorTexture, firstActor.getX(), firstActor.getY(),4*actorTexture.getWidth(),4*actorTexture.getWidth());//可控制绘制图像大小
189 | button_move.draw(batch, 1.0f);
190 | stage.draw();// 绘制舞台
191 | batch.end();
192 | Gdx.gl20.glEnable(GL20.GL_DEPTH_TEST);
193 | Gdx.gl20.glEnable(GL20.GL_TEXTURE);
194 | Gdx.gl20.glEnable(GL20.GL_TEXTURE_2D);
195 | // Gdx.gl20.glEnable(GL20.GL_LINE_SMOOTH);//old
196 | Gdx.gl20.glEnable(GL20.GL_LINE_LOOP);//54wall
197 | Gdx.gl20.glDepthFunc(GL20.GL_LEQUAL);
198 | Gdx.gl20.glClearDepthf(1.0F);
199 | camera.update(true);
200 | // camera.apply(Gdx.gl20);//old
201 | texture.bind();
202 |
203 | if (mode == Mode.waitForPictureReady) {
204 | /*注意deviceCameraControl.getPictureData()得到的是byte[],可见整体思路就是,
205 | *将Android摄像头得到byte[],然后将byte[]转换为Pixmap,最后将pixmap存为jpg,这样不适用Android端图片保存模式,
206 | *byte[]----Pixmap----jpg
207 | */
208 | if (deviceCameraControl.getPictureData() != null) {
209 | // camera picture was actually takentake Gdx Screenshot
210 | Pixmap screenshotPixmap = getScreenshot(0, 0,
211 | Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), true);
212 | Pixmap cameraPixmap = new Pixmap(
213 | deviceCameraControl.getPictureData(), 0,
214 | deviceCameraControl.getPictureData().length);
215 | merge2Pixmaps(cameraPixmap, screenshotPixmap);
216 | // we could call PixmapIO.writePNG(pngfile, cameraPixmap);
217 | //仅保存screenshot,对同一时间的图片进行保存然后进行比较
218 | Pixmap screenshotPixmap_test = getScreenshot(0, 0,
219 | Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), true);
220 | FileHandle jpgfile_screenshot = Gdx.files
221 | .external("a_SDK_fail/libGdxSnapshot" + "_" + date
222 | + "_screenshot.jpg");
223 | deviceCameraControl.saveAsJpeg(jpgfile_screenshot,
224 | screenshotPixmap_test);
225 | //仅保存cameraPixma,对同一时间的图片进行保存然后进行比较
226 | Pixmap cameraPixmap_test = new Pixmap(
227 | deviceCameraControl.getPictureData(), 0,
228 | deviceCameraControl.getPictureData().length);
229 | FileHandle jpgfile_cameraPixmap = Gdx.files
230 | .external("a_SDK_fail/libGdxSnapshot" + "_" + date
231 | + "_camera.jpg");
232 | deviceCameraControl.saveAsJpeg(jpgfile_cameraPixmap,
233 | cameraPixmap_test);
234 | //保存混合之后的相片
235 | FileHandle jpgfile = Gdx.files
236 | .external("a_SDK_fail/libGdxSnapshot" + "_" + date
237 | + ".jpg");
238 | Gdx.app.log("FileHandle", date);
239 | time_1 = System.currentTimeMillis();
240 | deviceCameraControl.saveAsJpeg(jpgfile, cameraPixmap);
241 | time_2 = System.currentTimeMillis();
242 | //可以得到35830ms=35s,所以非常忙,导致Mode非常缓慢的回到Mode.normal
243 | Gdx.app.log("cost", String.valueOf(time_2 - time_1));
244 | deviceCameraControl.stopPreviewAsync();
245 | //保存文件后,mode回到normal继续render循环,所以中间停顿和logcat长时间未动的其实是卡住了Org
246 | mode = Mode.normal;
247 |
248 | }
249 | }
250 | // 这个log将会一直出现,所以render其实是一直在执行
251 | // Gdx.app.log("mode", String.valueOf(i_render++));
252 | }
253 | //注意截图与Android设备摄像传回的图像整合时并非按我所看的视角进行
254 | private Pixmap merge2Pixmaps(Pixmap mainPixmap, Pixmap overlayedPixmap) {
255 | // merge to data and Gdx screen shot - but fix Aspect Ratio issues
256 | // between the screen and the camera
257 | Pixmap.setFilter(Filter.BiLinear);
258 | float mainPixmapAR = (float) mainPixmap.getWidth()
259 | / mainPixmap.getHeight();
260 | float overlayedPixmapAR = (float) overlayedPixmap.getWidth()
261 | / overlayedPixmap.getHeight();
262 | if (overlayedPixmapAR < mainPixmapAR) {
263 | int overlayNewWidth = (int) (((float) mainPixmap.getHeight() / overlayedPixmap
264 | .getHeight()) * overlayedPixmap.getWidth());
265 | int overlayStartX = (mainPixmap.getWidth() - overlayNewWidth) / 2;
266 | // Overlaying pixmaps
267 | mainPixmap.drawPixmap(overlayedPixmap, 0, 0,
268 | overlayedPixmap.getWidth(), overlayedPixmap.getHeight(),
269 | overlayStartX, 0, overlayNewWidth, mainPixmap.getHeight());
270 | } else {
271 | int overlayNewHeight = (int) (((float) mainPixmap.getWidth() / overlayedPixmap
272 | .getWidth()) * overlayedPixmap.getHeight());
273 | int overlayStartY = (mainPixmap.getHeight() - overlayNewHeight) / 2;
274 | // Overlaying pixmaps
275 | mainPixmap.drawPixmap(overlayedPixmap, 0, 0,
276 | overlayedPixmap.getWidth(), overlayedPixmap.getHeight(), 0,
277 | overlayStartY, mainPixmap.getWidth(), overlayNewHeight);
278 | }
279 | return mainPixmap;
280 | }
281 |
282 | public Pixmap getScreenshot(int x, int y, int w, int h, boolean flipY) {
283 |
284 | Gdx.gl.glPixelStorei(GL20.GL_PACK_ALIGNMENT, 1);
285 | final Pixmap pixmap = new Pixmap(w, h, Format.RGBA8888);
286 | ByteBuffer pixels = pixmap.getPixels();
287 | Gdx.gl.glReadPixels(x, y, w, h, GL20.GL_RGBA, GL20.GL_UNSIGNED_BYTE,
288 | pixels);
289 |
290 | final int numBytes = w * h * 4;
291 | byte[] lines = new byte[numBytes];
292 | if (flipY) {
293 | final int numBytesPerLine = w * 4;
294 | for (int i = 0; i < h; i++) {
295 | pixels.position((h - i - 1) * numBytesPerLine);
296 | pixels.get(lines, i * numBytesPerLine, numBytesPerLine);
297 | }
298 | pixels.clear();
299 | pixels.put(lines);
300 | } else {
301 | pixels.clear();
302 | pixels.get(lines);
303 | }
304 |
305 | return pixmap;
306 | }
307 |
308 | @Override
309 | public void resize(int width, int height) {
310 | camera = new PerspectiveCamera(67.0f, 2.0f * width / height, 2.0f);
311 | camera.far = 100.0f;
312 | camera.near = 0.1f;
313 | camera.position.set(2.0f, 2.0f, 2.0f);
314 | camera.lookAt(0.0f, 0.0f, 0.0f);
315 |
316 | }
317 |
318 | @Override
319 | public void pause() {
320 | }
321 |
322 | @Override
323 | public void resume() {
324 | }
325 |
326 | ClickListener preview_on = new ClickListener() {
327 |
328 | @Override
329 | public void clicked(InputEvent event, float x, float y) {
330 | Gdx.app.log("preview_on", "preview_on按钮被点击了");
331 | if (mode == Mode.waitForPictureReady) {
332 | mode = Mode.normal;
333 | }
334 | if (mode == Mode.normal) {
335 | mode = Mode.prepare;
336 | if (deviceCameraControl != null) {
337 | deviceCameraControl.prepareCameraAsync();
338 | }
339 | }
340 | }
341 |
342 | };
343 |
344 | //控制人物移动
345 | ClickListener actor_move = new ClickListener() {
346 |
347 | @Override
348 | public void clicked(InputEvent event, float x, float y) {
349 | firstActor.setX(firstActor.getX() + 55);
350 | Gdx.app.log("actor_move", "actor_move按钮被点击了");
351 | }
352 |
353 | };
354 |
355 | ClickListener preview_on_1 = new ClickListener() {
356 |
357 | @Override
358 | public void clicked(InputEvent event, float x, float y) {
359 | Gdx.app.log("preview_on_1", "preview_on_1按钮被点击了");
360 | if (mode == Mode.preview) {
361 | mode = Mode.takePicture;
362 | }
363 |
364 | }
365 |
366 | };
367 |
368 | ClickListener preview_off = new ClickListener() {
369 | @Override
370 | public void clicked(InputEvent event, float x, float y) {
371 | Gdx.app.log("preview_on", "1按钮被点击了");
372 | if (mode == Mode.waitForPictureReady) {
373 | mode = Mode.normal;
374 | }
375 |
376 | if (mode == Mode.normal) {
377 | mode = Mode.prepare;
378 | if (deviceCameraControl != null) {
379 | deviceCameraControl.prepareCameraAsync();
380 | }
381 | }
382 |
383 | }
384 | };
385 |
386 | }
387 |
--------------------------------------------------------------------------------
/old_version/ver_2016.7.21.11.18/core/src/com/mygdx/game0606/MyGdxGame0606.java:
--------------------------------------------------------------------------------
1 | package com.mygdx.game0606;
2 |
3 | import java.nio.ByteBuffer;
4 | import java.text.SimpleDateFormat;
5 |
6 | import com.badlogic.gdx.Application;
7 | import com.badlogic.gdx.ApplicationListener;
8 | import com.badlogic.gdx.Gdx;
9 | import com.badlogic.gdx.files.FileHandle;
10 | import com.badlogic.gdx.graphics.Color;
11 | import com.badlogic.gdx.graphics.GL20;//oldGL20
12 | import com.badlogic.gdx.graphics.Mesh;
13 | import com.badlogic.gdx.graphics.PerspectiveCamera;
14 | import com.badlogic.gdx.graphics.Pixmap;
15 | import com.badlogic.gdx.graphics.Texture;
16 | import com.badlogic.gdx.graphics.Texture.TextureFilter;
17 | import com.badlogic.gdx.graphics.VertexAttribute;
18 | import com.badlogic.gdx.graphics.Pixmap.Filter;
19 | import com.badlogic.gdx.graphics.Pixmap.Format;
20 | import com.badlogic.gdx.graphics.VertexAttributes.Usage;
21 | import com.badlogic.gdx.graphics.g2d.BitmapFont;
22 | import com.badlogic.gdx.graphics.g2d.SpriteBatch;
23 | import com.badlogic.gdx.graphics.g2d.TextureRegion;
24 | import com.badlogic.gdx.graphics.glutils.ShaderProgram;
25 | import com.badlogic.gdx.scenes.scene2d.Actor;
26 | import com.badlogic.gdx.scenes.scene2d.InputEvent;
27 | import com.badlogic.gdx.scenes.scene2d.Stage;
28 | import com.badlogic.gdx.scenes.scene2d.ui.Button;
29 | import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
30 | import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
31 | import com.badlogic.gdx.utils.viewport.StretchViewport;
32 | import com.mygdx.game0606.actor.FirstActor;
33 |
34 | public class MyGdxGame0606 implements ApplicationListener {
35 | /* http://blog.csdn.net/xietansheng/article/details/50187861 */
36 | private Stage stage;// 舞台
37 | private Texture actorTexture;
38 | private Texture move_1_Texture;
39 | private Texture move_2_Texture;
40 | private Texture upTexture;
41 | private Texture downTexture;
42 | private Button button;// 按钮
43 | private Button button_1;// 按钮
44 | private Button button_move;// 按钮
45 | // 视口世界的宽高统使用 480 * 800, 并统一使用伸展视口(StretchViewport)
46 | public static final float WORLD_WIDTH = 800;
47 | public static final float WORLD_HEIGHT = 600;
48 | /* 54wall */
49 | public SpriteBatch batch;
50 | public Texture texture_demo;
51 | private SimpleDateFormat sDateFormat = new SimpleDateFormat(
52 | "yyyy-MM-dd hh:mm:ss");
53 | private String date = sDateFormat.format(new java.util.Date());
54 |
55 | public enum Mode {
56 | normal, prepare, preview, takePicture, waitForPictureReady,
57 | }
58 |
59 | public int state_normal = 0;
60 | public int state_prepare = 1;
61 |
62 | public Constant constant = new Constant();
63 |
64 | public static final short facesVerticesIndex[][] = { { 0, 1, 2, 3 },
65 | { 4, 5, 6, 7 }, { 8, 9, 10, 11 }, { 12, 13, 14, 15 },
66 | { 16, 17, 18, 19 }, { 20, 21, 22, 23 } };
67 |
68 | private final static VertexAttribute verticesAttributes[] = new VertexAttribute[] {
69 | new VertexAttribute(Usage.Position, 3, "a_position"),
70 | new VertexAttribute(Usage.ColorPacked, 4, "a_color"),
71 | new VertexAttribute(Usage.TextureCoordinates, 2, "a_texCoords"), };
72 |
73 | private Texture texture;
74 |
75 | private Mesh[] mesh = new Mesh[6];
76 |
77 | private PerspectiveCamera camera;
78 |
79 | private Mode mode = Mode.normal;
80 |
81 | private final DeviceCameraControl deviceCameraControl;
82 | private long time_1;
83 | private long time_2;
84 | private int i_render = 0;
85 |
86 | private Actor firstActor;
87 |
88 | /*
89 | * 通过this.deviceCameraControl=
90 | * cameraControl获取Android端摄像头然后后续所有的deviceCameraControl实际调用的都是Android的东西
91 | */
92 | public MyGdxGame0606(DeviceCameraControl cameraControl) {
93 | this.deviceCameraControl = cameraControl;
94 | }
95 |
96 | @Override
97 | public void create() {
98 | /* http://blog.csdn.net/xietansheng/article/details/50187861 */
99 | // 设置日志输出级别
100 | Gdx.app.setLogLevel(Application.LOG_DEBUG);
101 | // 使用伸展视口(StretchViewport)创建舞台
102 | stage = new Stage(new StretchViewport(WORLD_WIDTH, WORLD_HEIGHT));
103 | // 将输入处理设置到舞台(必须设置, 否则点击按钮没效果)
104 | Gdx.input.setInputProcessor(stage);
105 | firstActor = new Actor();
106 | firstActor.setPosition(100, 300);
107 |
108 | /* 第 1 步: 创建 弹起 和 按下 两种状态的纹理 */
109 |
110 | move_1_Texture = new Texture(Gdx.files.internal("data/move_0.png"));
111 | move_2_Texture = new Texture(Gdx.files.internal("data/move_1.png"));
112 | actorTexture = new Texture(Gdx.files.internal("data/james.png"));
113 | upTexture = new Texture(Gdx.files.internal("data/button_1.png"));
114 | downTexture = new Texture(Gdx.files.internal("data/button_2.png"));
115 | /* 第 2 步: 创建 ButtonStyle */
116 | Button.ButtonStyle style_move = new Button.ButtonStyle();
117 | Button.ButtonStyle style = new Button.ButtonStyle();
118 | // 设置 style 的 弹起 和 按下 状态的纹理区域
119 | style_move.up=new TextureRegionDrawable(new TextureRegion(move_1_Texture));
120 | style_move.down=new TextureRegionDrawable(new TextureRegion(move_2_Texture));
121 |
122 | style.up = new TextureRegionDrawable(new TextureRegion(upTexture));
123 | style.down = new TextureRegionDrawable(new TextureRegion(downTexture));
124 | /* 第 3 步: 创建 Button */
125 |
126 | button_move = new Button(style_move);
127 | // 设置按钮的位置
128 | button_move.setPosition(100, 350);
129 | // 给按钮添加点击监听器
130 | button_move.addListener(actor_move);
131 |
132 |
133 |
134 | button = new Button(style);
135 | // 设置按钮的位置
136 | button.setPosition(100, 300);
137 | // 给按钮添加点击监听器
138 | button.addListener(preview_on);
139 |
140 | button_1 = new Button(style);
141 | // 设置按钮的位置
142 | button_1.setPosition(550, 400);
143 | // 给按钮添加点击监听器
144 | button_1.addListener(preview_on_1);
145 |
146 | /* 第 4 步: 添加 button 到舞台 */
147 | stage.addActor(button);
148 | stage.addActor(button_1);
149 | stage.addActor(button_move);
150 | stage.addActor(firstActor);
151 |
152 | /* 54wall */
153 | batch = new SpriteBatch();
154 | texture_demo = new Texture(Gdx.files.internal("data/1.png"));
155 | // Load the Libgdx splash screen texture
156 | texture = new Texture(Gdx.files.internal("data/libgdx.png"));
157 | texture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
158 |
159 | // Create the 6 faces of the Cube
160 | for (int i = 0; i < 6; i++) {
161 | mesh[i] = new Mesh(true, 24, 4, verticesAttributes);
162 | mesh[i].setVertices(Constant.vertexData);
163 | mesh[i].setIndices(facesVerticesIndex[i]);
164 | }
165 |
166 | // Create the OpenGL Camera,这里指的是视角,正交视角与设备摄像头完全不是一个东西
167 | camera = new PerspectiveCamera(67.0f, 2.0f * Gdx.graphics.getWidth()
168 | / Gdx.graphics.getHeight(), 2.0f);// oldfloat
169 | // fieldOfViewY改为37无反应
170 | camera.far = 100.0f;// old 改为50,无反应
171 |
172 | camera.near = 0.1f;
173 | camera.position.set(2.0f, 2.0f, 2.0f);
174 | camera.lookAt(0.0f, 0.0f, 0.0f);// old
175 |
176 | }
177 |
178 | /* 手动释放资源 */
179 | @Override
180 | public void dispose() {
181 | /* 对应button,应用退出时释放资源 */
182 | if (upTexture != null) {
183 | upTexture.dispose();
184 | }
185 | if (downTexture != null) {
186 | downTexture.dispose();
187 | }
188 | if (stage != null) {
189 | stage.dispose();
190 | }
191 | /* 54wall */
192 | batch.dispose();
193 | texture_demo.dispose();
194 |
195 | texture.dispose();
196 | for (int i = 0; i < 6; i++) {
197 | mesh[i].dispose();
198 | mesh[i] = null;
199 | }
200 | texture = null;
201 | }
202 |
203 | /* 通过debug发现,每次点击运行(断点在render内)render都会一直运行,可见render作为渲染的一个覆盖函数的确是处于一直运行的状态 */
204 | @Override
205 | public void render() {
206 | /*如何控制render一进入就使Android相机进入preview,直接在render加入50 100计数器,保证在50之前为mode的一个状态,随着render的进行
207 | * 计数器进行计数,然后每次只执行一次deviceCameraControl,就可以直接进入相机的预览模式*/
208 | // Gdx.gl20.glClearColor(0.0f, 0f, 0.0f, 0.0f);//黑
209 | // Gdx.gl.glClearColor(1, 1, 1, 1);// 设置背景为白色
210 | Gdx.gl.glClearColor(0.57f, 0.40f, 0.55f, 1.0f);// 紫色
211 | Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);// 清屏
212 | render_preview();
213 |
214 | }
215 |
216 | /*
217 | * 1 发现在打开摄像头后,button全部失效,只有没有camera预览时,button才有效,是不是渲染时摄像头与绘制的button存在冲突
218 | * 并且在调试button时,屏幕处于按压状态也是和button冲突了
219 | *
220 | * 2
221 | * 现在实现的功能是按下左按钮,开始预览,按下右侧按钮进行聚焦拍摄,这说明在mode为preview状态时,button是可以相应的之前却一直不可以
222 | */
223 | public void render_preview() {
224 | /* 我已经将preview变为takePicture状态移动到click中,实现先预览再拍照 */
225 | Gdx.gl20.glHint(GL20.GL_GENERATE_MIPMAP_HINT, GL20.GL_NICEST);
226 | if (mode == Mode.takePicture) {
227 | /* 没有清屏,摄像头的预览功能就没有,演员和舞台在各个if中可以不加 */
228 | Gdx.gl20.glClearColor(0f, 0.0f, 0.0f, 0.0f);
229 | if (deviceCameraControl != null) {
230 | deviceCameraControl.takePicture();
231 | }
232 | mode = Mode.waitForPictureReady;
233 | } else if (mode == Mode.waitForPictureReady) {
234 | Gdx.gl20.glClearColor(0.0f, 0f, 0.0f, 0.0f);
235 | } else if (mode == Mode.prepare) {
236 | Gdx.gl20.glClearColor(0.0f, 0.0f, 0f, 0.6f);
237 | if (deviceCameraControl != null) {
238 | if (deviceCameraControl.isReady()) {
239 | deviceCameraControl.startPreviewAsync();
240 | mode = Mode.preview;
241 | }
242 | }
243 | } else if (mode == Mode.preview) {
244 | Gdx.gl20.glClearColor(0.0f, 0.0f, 0.0f, 0f);
245 | } else {
246 | /* mode = normal */
247 | Gdx.gl20.glClearColor(0.0f, 0.0f, 0.6f, 1.0f);
248 |
249 | }
250 | Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
251 | /* 下边放到texture.bind();时效果一致 */
252 | batch.begin();
253 |
254 | stage.act(); // 更新舞台逻辑
255 | /* 新增演员 ,放到这里才会显示*/
256 | // batch.draw(actorTexture, 100, 300);//这么写,每次的移动无效,因为render画的动作被写死了
257 | batch.draw(actorTexture, firstActor.getX(), firstActor.getY());
258 | batch.draw(texture, 480, 480, texture.getWidth(), texture.getHeight());
259 | button.draw(batch, 1.0F);// 仅绘制actor
260 | button_1.draw(batch, 1.0F);
261 | button_move.draw(batch, 1.0f);
262 | /* 新增演员 ,放到这里不会显示*/
263 | // batch.draw(actorTexture, 100, 300);
264 |
265 | stage.draw();// 绘制舞台
266 | // batch.draw(texture, 0, 0, 960, 540);
267 | batch.end();
268 |
269 | Gdx.gl20.glEnable(GL20.GL_DEPTH_TEST);
270 | Gdx.gl20.glEnable(GL20.GL_TEXTURE);
271 | Gdx.gl20.glEnable(GL20.GL_TEXTURE_2D);
272 | // Gdx.gl20.glEnable(GL20.GL_LINE_SMOOTH);//54wall old
273 | Gdx.gl20.glEnable(GL20.GL_LINE_LOOP);// new
274 | Gdx.gl20.glDepthFunc(GL20.GL_LEQUAL);
275 | Gdx.gl20.glClearDepthf(1.0F);
276 | camera.update(true);
277 | // camera.apply(Gdx.gl20);//54wall old
278 | texture.bind();
279 |
280 | if (mode == Mode.waitForPictureReady) {
281 | /*
282 | * 注意deviceCameraControl.getPictureData()得到的是byte[],可见整体思路就是,
283 | * 将Android摄像头得到byte[],然后
284 | * 将byte[]转换为Pixmap,最后将pixmap存为jpg,这样不适用Android端图片保存模式,
285 | * byte[]----Pixmap----jpg
286 | */
287 | if (deviceCameraControl.getPictureData() != null) {
288 | // camera picture was actually takentake Gdx Screenshot
289 | Pixmap screenshotPixmap = getScreenshot(0, 0,
290 | Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), true);
291 | /* 开始报错deviceCameraControl.getPictureData一直未null */
292 | Pixmap cameraPixmap = new Pixmap(
293 | deviceCameraControl.getPictureData(), 0,
294 | deviceCameraControl.getPictureData().length);
295 | merge2Pixmaps(cameraPixmap, screenshotPixmap);
296 | // we could call PixmapIO.writePNG(pngfile, cameraPixmap);
297 | /* 仅保存screenshot,对同一时间的图片进行保存然后进行比较 */
298 | Pixmap screenshotPixmap_test = getScreenshot(0, 0,
299 | Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), true);
300 | FileHandle jpgfile_screenshot = Gdx.files
301 | .external("a_SDK_fail/libGdxSnapshot" + "_" + date
302 | + "_screenshot.jpg");
303 | deviceCameraControl.saveAsJpeg(jpgfile_screenshot,
304 | screenshotPixmap_test);
305 | /* 仅保存cameraPixma,对同一时间的图片进行保存然后进行比较 */
306 | Pixmap cameraPixmap_test = new Pixmap(
307 | deviceCameraControl.getPictureData(), 0,
308 | deviceCameraControl.getPictureData().length);
309 |
310 | FileHandle jpgfile_cameraPixmap = Gdx.files
311 | .external("a_SDK_fail/libGdxSnapshot" + "_" + date
312 | + "_camera.jpg");
313 | deviceCameraControl.saveAsJpeg(jpgfile_cameraPixmap,
314 | cameraPixmap_test);
315 |
316 | /* 保存混合之后的相片 */
317 | FileHandle jpgfile = Gdx.files
318 | .external("a_SDK_fail/libGdxSnapshot" + "_" + date
319 | + ".jpg");
320 | Gdx.app.log("FileHandle", date);
321 | time_1 = System.currentTimeMillis();
322 | deviceCameraControl.saveAsJpeg(jpgfile, cameraPixmap);
323 | time_2 = System.currentTimeMillis();
324 | /* 可以得到35830ms=35s,所以非常忙,导致Mode非常缓慢的回到Mode.normal */
325 | Gdx.app.log("cost", String.valueOf(time_2 - time_1));
326 | deviceCameraControl.stopPreviewAsync();
327 | /* 保存文件后,mode回到normal继续render循环,所以中间停顿的其实是卡住了?! */
328 | mode = Mode.normal;
329 |
330 | }
331 | }
332 | /* 这个log将会一直出现,所以render其实是一直在执行 */
333 | // Gdx.app.log("mode", String.valueOf(mode));
334 | // Gdx.app.log("mode", String.valueOf(i_render++));
335 | }
336 |
337 | /* 随手加一个log是很重要的 */
338 | public void takePicture4render() {
339 | /*
340 | * 进入app后,手按住屏幕不放,才能进入预览模式,放开就直接拍照了
341 | * input.isTouched(1)可能与button点击存在冲突,所以必须屏蔽
342 | */
343 | // if (Gdx.input.isTouched(1)) {
344 | //
345 | // mode = Mode.normal;
346 | // Gdx.app.log("doube", String.valueOf(mode));
347 | // }
348 | //
349 | //
350 | // if (Gdx.input.isTouched()) {
351 | // if (mode == Mode.normal) {
352 | // mode = Mode.prepare;
353 | // if (deviceCameraControl != null) {
354 | // deviceCameraControl.prepareCameraAsync();
355 | // }
356 | // }
357 | // } else {
358 | // // touch removed
359 | // if (mode == Mode.preview) {
360 | // mode = Mode.takePicture;
361 | // }
362 | // }
363 |
364 | /* 我想让摄像头一直处于预览状态 */
365 | // if (deviceCameraControl != null) {
366 | // deviceCameraControl.prepareCameraAsync();
367 | // }
368 |
369 | /* 仅跟进入预览后直接进入拍照模式 */
370 | if (mode == Mode.preview) {
371 | mode = Mode.takePicture;
372 | }
373 |
374 | // Gdx.gl20.glHint(GL20.GL_PERSPECTIVE_CORRECTION_HINT,
375 | // GL20.GL_NICEST);//old 54wall
376 | Gdx.gl20.glHint(GL20.GL_GENERATE_MIPMAP_HINT, GL20.GL_NICEST);
377 | if (mode == Mode.takePicture) {
378 | /* 没有清屏,摄像头的预览功能就没有 */
379 | Gdx.gl20.glClearColor(0f, 0.0f, 0.0f, 0.0f);
380 | batch.begin();
381 | stage.act(); // 更新舞台逻辑
382 | button.draw(batch, 1.0F);// 仅绘制actor
383 | stage.draw();// 绘制舞台
384 | batch.draw(texture, 0, 0, 960, 540);
385 | batch.end();
386 |
387 | if (deviceCameraControl != null) {
388 | deviceCameraControl.takePicture();
389 |
390 | }
391 | mode = Mode.waitForPictureReady;
392 | } else if (mode == Mode.waitForPictureReady) {
393 | Gdx.gl20.glClearColor(0.0f, 0f, 0.0f, 0.0f);
394 | batch.begin();
395 | stage.act(); // 更新舞台逻辑
396 | button.draw(batch, 1.0F);// 仅绘制actor
397 | stage.draw();// 绘制舞台
398 | batch.draw(texture, 0, 0, 960, 540);
399 | batch.end();
400 |
401 | } else if (mode == Mode.prepare) {
402 | Gdx.gl20.glClearColor(0.0f, 0.0f, 0f, 0.0f);
403 | batch.begin();
404 | stage.act(); // 更新舞台逻辑
405 | button.draw(batch, 1.0F);// 仅绘制actor
406 | stage.draw();// 绘制舞台
407 | batch.draw(texture, 0, 0, 960, 540);
408 | batch.end();
409 | if (deviceCameraControl != null) {
410 | if (deviceCameraControl.isReady()) {
411 | deviceCameraControl.startPreviewAsync();
412 | mode = Mode.preview;
413 | }
414 | }
415 | } else if (mode == Mode.preview) {
416 | Gdx.gl20.glClearColor(0.0f, 0.0f, 0.0f, 0f);
417 | batch.begin();
418 | stage.act(); // 更新舞台逻辑
419 | button.draw(batch, 1.0F);// 仅绘制actor
420 | stage.draw();// 绘制舞台
421 | batch.draw(texture, 0, 0, 960, 540);
422 | batch.end();
423 | } else {
424 | /* mode = normal */
425 | Gdx.gl20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
426 | batch.begin();
427 | stage.act(); // 更新舞台逻辑
428 | button.draw(batch, 1.0F);// 仅绘制actor
429 | stage.draw();// 绘制舞台
430 | batch.draw(texture, 0, 0, 960, 540);
431 | batch.end();
432 | }
433 | Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
434 |
435 | batch.begin();
436 | stage.act(); // 更新舞台逻辑
437 | button.draw(batch, 1.0F);// 仅绘制actor
438 | stage.draw();// 绘制舞台
439 | batch.draw(texture, 0, 0, 960, 540);
440 | batch.end();
441 |
442 | Gdx.gl20.glEnable(GL20.GL_DEPTH_TEST);
443 | Gdx.gl20.glEnable(GL20.GL_TEXTURE);
444 | Gdx.gl20.glEnable(GL20.GL_TEXTURE_2D);
445 | // Gdx.gl20.glEnable(GL20.GL_LINE_SMOOTH);//54wall old
446 | Gdx.gl20.glEnable(GL20.GL_LINE_LOOP);// new
447 | Gdx.gl20.glDepthFunc(GL20.GL_LEQUAL);
448 | Gdx.gl20.glClearDepthf(1.0F);
449 | camera.update(true);
450 | // camera.apply(Gdx.gl20);//54wall old
451 | texture.bind();
452 | for (int i = 0; i < 6; i++) {
453 | /*
454 | * 可以尝试直接使用上述代码,对一张渲染的图片进行剪切,或者使用三角形代替这里这么多的网格,然后看效果
455 | * http://blog.sina.com.cn/s/blog_940dd50a0101fl4s.html
456 | */
457 | // mesh[i].render( GL20.GL_TRIANGLE_FAN, 0 ,4);//54wall old
458 | // ShaderProgram shader = new ShaderProgram(1 1);//原来的数目一样,不知道会不会影响
459 | // ShaderProgram shader = new ShaderProgram(String.valueOf(i),
460 | // String.valueOf(i+1));//54new
461 | // mesh[i].render(shader, GL20.GL_TRIANGLE_FAN, 0, 4);//54new
462 | }
463 | if (mode == Mode.waitForPictureReady) {
464 | /*
465 | * 注意deviceCameraControl.getPictureData()得到的是byte[],可见整体思路就是,
466 | * 将Android摄像头得到byte[],然后
467 | * 将byte[]转换为Pixmap,最后将pixmap存为jpg,这样不适用Android端图片保存模式,
468 | * byte[]----Pixmap----jpg
469 | */
470 | if (deviceCameraControl.getPictureData() != null) {
471 | // camera picture was actually takentake Gdx Screenshot
472 | Pixmap screenshotPixmap = getScreenshot(0, 0,
473 | Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), true);
474 |
475 | Pixmap cameraPixmap = new Pixmap(
476 | deviceCameraControl.getPictureData(), 0,
477 | deviceCameraControl.getPictureData().length);
478 |
479 | merge2Pixmaps(cameraPixmap, screenshotPixmap);
480 | // we could call PixmapIO.writePNG(pngfile, cameraPixmap);
481 | /* 现在有一个问题就是每次都是拍照两次,才有一张图片 */
482 | FileHandle jpgfile = Gdx.files
483 | .external("a_SDK_fail/libGdxSnapshot" + "_" + date
484 | + ".jpg");
485 | Gdx.app.log("FileHandle", date);
486 | time_1 = System.currentTimeMillis();
487 | deviceCameraControl.saveAsJpeg(jpgfile, cameraPixmap);
488 |
489 | time_2 = System.currentTimeMillis();
490 | /* 可以得到35830ms=35s,所以非常忙,导致Mode非常缓慢的回到Mode.normal */
491 | Gdx.app.log("cost", String.valueOf(time_2 - time_1));
492 | deviceCameraControl.stopPreviewAsync();
493 | /* 保存文件后,mode回到normal继续render循环,所以中间停顿的其实是卡住了?! */
494 | mode = Mode.normal;
495 |
496 | }
497 | }
498 | /* 这个log将会一直出现 */
499 | Gdx.app.log("mode", String.valueOf(mode));
500 | }
501 |
502 | /* 注意截图与Android设备摄像传回的图像整合时并非按我所看的视角进行 */
503 | private Pixmap merge2Pixmaps(Pixmap mainPixmap, Pixmap overlayedPixmap) {
504 | // merge to data and Gdx screen shot - but fix Aspect Ratio issues
505 | // between the screen and the camera
506 | Pixmap.setFilter(Filter.BiLinear);
507 | float mainPixmapAR = (float) mainPixmap.getWidth()
508 | / mainPixmap.getHeight();
509 | float overlayedPixmapAR = (float) overlayedPixmap.getWidth()
510 | / overlayedPixmap.getHeight();
511 | if (overlayedPixmapAR < mainPixmapAR) {
512 | int overlayNewWidth = (int) (((float) mainPixmap.getHeight() / overlayedPixmap
513 | .getHeight()) * overlayedPixmap.getWidth());
514 | int overlayStartX = (mainPixmap.getWidth() - overlayNewWidth) / 2;
515 | // Overlaying pixmaps
516 | mainPixmap.drawPixmap(overlayedPixmap, 0, 0,
517 | overlayedPixmap.getWidth(), overlayedPixmap.getHeight(),
518 | overlayStartX, 0, overlayNewWidth, mainPixmap.getHeight());
519 | } else {
520 | int overlayNewHeight = (int) (((float) mainPixmap.getWidth() / overlayedPixmap
521 | .getWidth()) * overlayedPixmap.getHeight());
522 | int overlayStartY = (mainPixmap.getHeight() - overlayNewHeight) / 2;
523 | // Overlaying pixmaps
524 | mainPixmap.drawPixmap(overlayedPixmap, 0, 0,
525 | overlayedPixmap.getWidth(), overlayedPixmap.getHeight(), 0,
526 | overlayStartY, mainPixmap.getWidth(), overlayNewHeight);
527 | }
528 | return mainPixmap;
529 | }
530 |
531 | public Pixmap getScreenshot(int x, int y, int w, int h, boolean flipY) {
532 |
533 | Gdx.gl.glPixelStorei(GL20.GL_PACK_ALIGNMENT, 1);
534 | final Pixmap pixmap = new Pixmap(w, h, Format.RGBA8888);
535 | ByteBuffer pixels = pixmap.getPixels();
536 | Gdx.gl.glReadPixels(x, y, w, h, GL20.GL_RGBA, GL20.GL_UNSIGNED_BYTE,
537 | pixels);
538 |
539 | final int numBytes = w * h * 4;
540 | byte[] lines = new byte[numBytes];
541 | if (flipY) {
542 | final int numBytesPerLine = w * 4;
543 | for (int i = 0; i < h; i++) {
544 | pixels.position((h - i - 1) * numBytesPerLine);
545 | pixels.get(lines, i * numBytesPerLine, numBytesPerLine);
546 | }
547 | pixels.clear();
548 | pixels.put(lines);
549 | } else {
550 | pixels.clear();
551 | pixels.get(lines);
552 | }
553 |
554 | return pixmap;
555 | }
556 |
557 | @Override
558 | public void resize(int width, int height) {
559 | camera = new PerspectiveCamera(67.0f, 2.0f * width / height, 2.0f);
560 | camera.far = 100.0f;
561 | camera.near = 0.1f;
562 | camera.position.set(2.0f, 2.0f, 2.0f);
563 | camera.lookAt(0.0f, 0.0f, 0.0f);
564 |
565 | }
566 |
567 | @Override
568 | public void pause() {
569 | }
570 |
571 | @Override
572 | public void resume() {
573 | }
574 |
575 | ClickListener preview_on = new ClickListener() {
576 |
577 | @Override
578 | public void clicked(InputEvent event, float x, float y) {
579 | Gdx.app.log("preview_on", "preview_on按钮被点击了");
580 | if (mode == Mode.waitForPictureReady) {
581 | mode = Mode.normal;
582 | }
583 |
584 | if (mode == Mode.normal) {
585 | mode = Mode.prepare;
586 | if (deviceCameraControl != null) {
587 | deviceCameraControl.prepareCameraAsync();
588 | }
589 | }
590 | }
591 |
592 | };
593 |
594 |
595 | ClickListener actor_move = new ClickListener() {
596 |
597 | @Override
598 | public void clicked(InputEvent event, float x, float y) {
599 |
600 | firstActor.setX(firstActor.getX() + 55);
601 |
602 | Gdx.app.log("actor_move", "actor_move按钮被点击了");
603 | }
604 |
605 | };
606 |
607 | ClickListener preview_on_1 = new ClickListener() {
608 |
609 | @Override
610 | public void clicked(InputEvent event, float x, float y) {
611 | Gdx.app.log("preview_on_1", "preview_on_1按钮被点击了");
612 | if (mode == Mode.preview) {
613 | mode = Mode.takePicture;
614 | }
615 |
616 | }
617 |
618 | };
619 |
620 | ClickListener preview_off = new ClickListener() {
621 | @Override
622 | public void clicked(InputEvent event, float x, float y) {
623 | Gdx.app.log("preview_on", "1按钮被点击了");
624 | /*
625 | * 不等输入,直接写mode =
626 | * Mode.takePicture;相当于deviceCameraControl.prepareCameraAsync
627 | * ();没有写,会报空指针 java.lang.NullPointerException at
628 | * com.mygdx.game0606.android.AndroidDeviceCameraController
629 | * .takePicture(AndroidDeviceCameraController.java:122)
630 | */
631 |
632 | /*
633 | * takePicture4render不能写在这里,因为batch.draw(texture, 0, 0, 960,
634 | * 540);应该在render中完成
635 | */
636 | // takePicture4render();
637 | /*
638 | * 增加下面语句后可以完成点击按钮进行拍照,关键就是让Mode进行一个完整的循环
639 | * 程序循环成Mode.normal时,屏幕再次回到黑色,才表示循环完成一次
640 | */
641 | if (mode == Mode.waitForPictureReady) {
642 | mode = Mode.normal;
643 | }
644 |
645 | if (mode == Mode.normal) {
646 | mode = Mode.prepare;
647 | if (deviceCameraControl != null) {
648 | /*
649 | * 首先button的点击可能与Gdx.input.isTouched()输入检测有冲突,然后,
650 | * 通过仅屏蔽deviceCameraControl.prepareCameraAsync();
651 | * 发现代码在render后
652 | * ,button依然有效,但是prepareCameraAsync后button失效,确认代码范围
653 | */
654 | deviceCameraControl.prepareCameraAsync();
655 | }
656 | }
657 | /* Mode.prepare之后不是Mode.preview,所以不能直接接入下边 */
658 | // if (mode == Mode.preview) {
659 | // mode = Mode.takePicture;
660 | // }
661 |
662 | }
663 | };
664 |
665 | }
666 |
--------------------------------------------------------------------------------
/old_version/core/src/com/mygdx/game0606/MyGdxGame0606.java:
--------------------------------------------------------------------------------
1 | package com.mygdx.game0606;
2 |
3 |
4 | import java.nio.ByteBuffer;
5 | import java.text.SimpleDateFormat;
6 | import java.util.ArrayList;
7 | import java.util.List;
8 |
9 | import com.badlogic.gdx.Application;
10 | import com.badlogic.gdx.ApplicationListener;
11 | import com.badlogic.gdx.Gdx;
12 | import com.badlogic.gdx.files.FileHandle;
13 | import com.badlogic.gdx.graphics.Color;
14 | import com.badlogic.gdx.graphics.GL20;//oldGL20
15 | import com.badlogic.gdx.graphics.Mesh;
16 | import com.badlogic.gdx.graphics.PerspectiveCamera;
17 | import com.badlogic.gdx.graphics.Pixmap;
18 | import com.badlogic.gdx.graphics.Texture;
19 | import com.badlogic.gdx.graphics.Texture.TextureFilter;
20 | import com.badlogic.gdx.graphics.VertexAttribute;
21 | import com.badlogic.gdx.graphics.Pixmap.Filter;
22 | import com.badlogic.gdx.graphics.Pixmap.Format;
23 | import com.badlogic.gdx.graphics.VertexAttributes.Usage;
24 | import com.badlogic.gdx.graphics.g2d.BitmapFont;
25 | import com.badlogic.gdx.graphics.g2d.SpriteBatch;
26 | import com.badlogic.gdx.graphics.g2d.TextureRegion;
27 | import com.badlogic.gdx.graphics.glutils.ShaderProgram;
28 | import com.badlogic.gdx.scenes.scene2d.Actor;
29 | import com.badlogic.gdx.scenes.scene2d.InputEvent;
30 | import com.badlogic.gdx.scenes.scene2d.Stage;
31 | import com.badlogic.gdx.scenes.scene2d.ui.Button;
32 | import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
33 | import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
34 | import com.badlogic.gdx.utils.viewport.StretchViewport;
35 | import com.mygdx.game0606.actor.FirstActor;
36 |
37 | public class MyGdxGame0606 implements ApplicationListener {
38 | /* http://blog.csdn.net/xietansheng/article/details/50187861 */
39 | private Stage stage;// 舞台
40 | private Texture actorTexture;
41 | private Texture move_1_Texture;
42 | private Texture move_2_Texture;
43 | private Texture upTexture;
44 | private Texture downTexture;
45 | private Texture faceTexture;
46 | private Texture faceTexture_1;
47 | private Texture faceTexture_2;
48 | private Texture faceTexture_3;
49 | private Texture faceTexture_4;
50 | private List texturelisg=new ArrayList();
51 | private Button button;// 按钮
52 | private Button button_1;// 按钮
53 | private Button button_move;// 按钮
54 | // 视口世界的宽高统使用 480 * 800, 并统一使用伸展视口(StretchViewport)
55 | public static final float WORLD_WIDTH = 480;
56 | public static final float WORLD_HEIGHT = 800;
57 | public SpriteBatch batch;
58 | public Texture texture_demo;
59 | private SimpleDateFormat sDateFormat = new SimpleDateFormat(
60 | "yyyy-MM-dd hh:mm:ss");
61 | private String date = sDateFormat.format(new java.util.Date());
62 | public enum Mode {
63 | normal, prepare, preview, takePicture, waitForPictureReady,
64 | }
65 | public int state_normal = 0;
66 | public int state_prepare = 1;
67 | public Constant constant = new Constant();
68 | public static final short facesVerticesIndex[][] = { { 0, 1, 2, 3 },
69 | { 4, 5, 6, 7 }, { 8, 9, 10, 11 }, { 12, 13, 14, 15 },
70 | { 16, 17, 18, 19 }, { 20, 21, 22, 23 } };
71 | private final static VertexAttribute verticesAttributes[] = new VertexAttribute[] {
72 | new VertexAttribute(Usage.Position, 3, "a_position"),
73 | new VertexAttribute(Usage.ColorPacked, 4, "a_color"),
74 | new VertexAttribute(Usage.TextureCoordinates, 2, "a_texCoords"), };
75 | private Texture texture;
76 | private Mesh[] mesh = new Mesh[6];
77 | private PerspectiveCamera camera;
78 | private Mode mode = Mode.normal;
79 | private final DeviceCameraControl deviceCameraControl;
80 | private long time_1;
81 | private long time_2;
82 | private int i_render = 0;
83 | private Actor firstActor;
84 | /*
85 | * 通过this.deviceCameraControl=
86 | * cameraControl获取Android端摄像头然后后续所有的deviceCameraControl实际调用的都是Android的东西
87 | */
88 | public MyGdxGame0606(DeviceCameraControl cameraControl) {
89 | this.deviceCameraControl = cameraControl;
90 | }
91 |
92 | @Override
93 | public void create() {
94 | /* http://blog.csdn.net/xietansheng/article/details/50187861 */
95 | // 设置日志输出级别
96 | Gdx.app.setLogLevel(Application.LOG_DEBUG);
97 | // 使用伸展视口(StretchViewport)创建舞台
98 | stage = new Stage(new StretchViewport(WORLD_WIDTH, WORLD_HEIGHT));
99 | // 将输入处理设置到舞台(必须设置, 否则点击按钮没效果)
100 | Gdx.input.setInputProcessor(stage);
101 | firstActor = new Actor();
102 | firstActor.setHeight(150);
103 | firstActor.setWidth(150);
104 | firstActor.setPosition(150, 150);
105 | move_1_Texture = new Texture(Gdx.files.internal("data/play.png"));
106 | move_2_Texture = new Texture(Gdx.files.internal("data/start.png"));
107 | actorTexture = new Texture(Gdx.files.internal("data/cat_0.png"));
108 | upTexture = new Texture(Gdx.files.internal("data/start.png"));
109 | downTexture = new Texture(Gdx.files.internal("data/takepictures.png"));
110 | // faceTexture=new Texture(Gdx.files.external("a_SDK_fail/1.jpg"));
111 | // faceTexture_1=new Texture(Gdx.files.external("a_SDK_fail/1.jpg"));
112 | // faceTexture_2=new Texture(Gdx.files.external("a_SDK_fail/2.jpg"));
113 | // faceTexture_3=new Texture(Gdx.files.external("a_SDK_fail/3.jpg"));
114 | // faceTexture_4=new Texture(Gdx.files.external("a_SDK_fail/4.jpg"));
115 |
116 | //创建 ButtonStyle
117 | Button.ButtonStyle style_move = new Button.ButtonStyle();
118 | Button.ButtonStyle style = new Button.ButtonStyle();
119 | style_move.up=new TextureRegionDrawable(new TextureRegion(move_1_Texture));
120 | style_move.down=new TextureRegionDrawable(new TextureRegion(move_2_Texture));
121 | style.up = new TextureRegionDrawable(new TextureRegion(upTexture));
122 | style.down = new TextureRegionDrawable(new TextureRegion(downTexture));
123 | button_move = new Button(style_move);
124 | // 设置按钮的位置
125 | button_move.setPosition(150, 300);
126 | // 给按钮添加点击监听器
127 | button_move.addListener(actor_move);
128 | button = new Button(style);
129 | // 设置按钮的位置
130 | button.setPosition(50, 300);
131 | // 给按钮添加点击监听器
132 | button.addListener(preview_on);
133 | button_1 = new Button(style);
134 | // 设置按钮的位置
135 | button_1.setPosition(300, 300);
136 | // 给按钮添加点击监听器
137 | button_1.addListener(preview_on_1);
138 | //添加 button 到舞台
139 | stage.addActor(button);
140 | stage.addActor(button_1);
141 | stage.addActor(button_move);
142 | stage.addActor(firstActor);
143 | batch = new SpriteBatch();
144 | texture_demo = new Texture(Gdx.files.internal("data/1.png"));
145 | // Load the Libgdx splash screen texture
146 | texture = new Texture(Gdx.files.internal("data/bg.png"));
147 | texture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
148 | // Create the 6 faces of the Cube
149 | for (int i = 0; i < 6; i++) {
150 | mesh[i] = new Mesh(true, 24, 4, verticesAttributes);
151 | mesh[i].setVertices(Constant.vertexData);
152 | mesh[i].setIndices(facesVerticesIndex[i]);
153 | }
154 | // Create the OpenGL Camera,这里指的是视角,正交视角与设备摄像头完全不是一个东西
155 | camera = new PerspectiveCamera(67.0f, 2.0f * Gdx.graphics.getWidth()
156 | / Gdx.graphics.getHeight(), 2.0f);// oldfloat// fieldOfViewY改为37无反应
157 | camera.far = 100.0f;// old 改为50,无反应
158 | camera.near = 0.1f;
159 | camera.position.set(2.0f, 2.0f, 2.0f);
160 | camera.lookAt(0.0f, 0.0f, 0.0f);// old
161 |
162 | }
163 |
164 | /* 手动释放资源 */
165 | @Override
166 | public void dispose() {
167 | /* 对应button,应用退出时释放资源 */
168 | if (upTexture != null) {
169 | upTexture.dispose();
170 | }
171 | if (downTexture != null) {
172 | downTexture.dispose();
173 | }
174 | if (stage != null) {
175 | stage.dispose();
176 | }
177 | /* 54wall */
178 | batch.dispose();
179 | texture_demo.dispose();
180 |
181 | texture.dispose();
182 | for (int i = 0; i < 6; i++) {
183 | mesh[i].dispose();
184 | mesh[i] = null;
185 | }
186 | texture = null;
187 | }
188 |
189 | /* 通过debug发现,每次点击运行(断点在render内)render都会一直运行,可见render作为渲染的一个覆盖函数的确是处于一直运行的状态 */
190 | @Override
191 | public void render() {
192 | /*如何控制render一进入就使Android相机进入preview,直接在render加入50 100计数器,保证在50之前为mode的一个状态,随着render的进行
193 | * 计数器进行计数,然后每次只执行一次deviceCameraControl,就可以直接进入相机的预览模式*/
194 | // Gdx.gl20.glClearColor(0.0f, 0f, 0.0f, 0.0f);//黑
195 | // Gdx.gl.glClearColor(1, 1, 1, 1);// 设置背景为白色
196 | Gdx.gl.glClearColor(0.57f, 0.40f, 0.55f, 1.0f);// 紫色
197 | Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);// 清屏
198 | /*绘制视频帧*/
199 | i_render++;
200 | if (i_render==60) {
201 | i_render=1;
202 | }
203 |
204 | faceTexture=new Texture(Gdx.files.external("a_SDK_fail/"+i_render+".jpg"));
205 | batch.begin();
206 | batch.draw(faceTexture, 0, 0, faceTexture.getWidth(), faceTexture.getHeight());
207 | batch.end();
208 | faceTexture.dispose();//没有直接gc,有了之后也有GC,但是画面依然在动
209 | /*调用Android摄像头*/
210 | // render_preview();
211 |
212 | }
213 |
214 | /*1 发现在打开摄像头后,button全部失效,只有没有camera预览时,button才有效,是不是渲染时摄像头与绘制的button存在冲突
215 | * 并且在调试button时,屏幕处于按压状态也是和button冲突了
216 | * 2现在实现的功能是按下左按钮,开始预览,按下右侧按钮进行聚焦拍摄,这说明在mode为preview状态时,button是可以相应的之前却一直不可以*/
217 | public void render_preview() {
218 | /* 我已经将preview变为takePicture状态移动到click中,实现先预览再拍照 */
219 | Gdx.gl20.glHint(GL20.GL_GENERATE_MIPMAP_HINT, GL20.GL_NICEST);
220 | if (mode == Mode.takePicture) {
221 | /* 没有清屏,摄像头的预览功能就没有,演员和舞台在各个if中可以不加 */
222 | Gdx.gl20.glClearColor(0f, 0.0f, 0.0f, 0.0f);
223 | if (deviceCameraControl != null) {
224 | deviceCameraControl.takePicture();
225 | }
226 | mode = Mode.waitForPictureReady;
227 | } else if (mode == Mode.waitForPictureReady) {
228 | Gdx.gl20.glClearColor(0.0f, 0f, 0.0f, 0.0f);
229 | } else if (mode == Mode.prepare) {
230 | Gdx.gl20.glClearColor(0.0f, 0.0f, 0f, 0.6f);
231 | if (deviceCameraControl != null) {
232 | if (deviceCameraControl.isReady()) {
233 | deviceCameraControl.startPreviewAsync();
234 | mode = Mode.preview;
235 | }
236 | }
237 | } else if (mode == Mode.preview) {
238 | Gdx.gl20.glClearColor(0.0f, 0.0f, 0.0f, 0f);
239 | } else {
240 | /* mode = normal */
241 | Gdx.gl20.glClearColor(0.0f, 0.0f, 0.6f, 1.0f);
242 |
243 | }
244 | Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
245 | /* 下边放到texture.bind();时效果一致 */
246 | batch.begin();
247 |
248 | stage.act(); // 更新舞台逻辑
249 | /* 新增演员 ,放到这里才会显示*/
250 | // batch.draw(actorTexture, 100, 300);//这么写,每次的移动无效,因为render画的动作被写死了
251 | // batch.draw(actorTexture, firstActor.getX(), firstActor.getY());
252 | // batch.draw(texture, 480, 480, texture.getWidth(), texture.getHeight());
253 | // batch.draw(texture, 0, 0, texture.getWidth(), texture.getHeight());
254 | batch.draw(texture, 0, 0, 3f*texture.getWidth(), 3f*texture.getHeight());
255 | Gdx.app.log("", String.valueOf(texture.getWidth()));
256 | //先绘制的就先出现,所以演员在texture上边,而不是被覆盖
257 | // batch.draw(actorTexture, firstActor.getX(), firstActor.getY());//原大小
258 | batch.draw(actorTexture, firstActor.getX(), firstActor.getY(),4*actorTexture.getWidth(),4*actorTexture.getWidth());//可控制绘制图像大小
259 | button.draw(batch, 1.0F);// 仅绘制actor
260 | button_1.draw(batch, 1.0F);
261 | button_move.draw(batch, 1.0f);
262 | /* 新增演员 ,放到这里不会显示*/
263 | // batch.draw(actorTexture, 100, 300);
264 | stage.draw();// 绘制舞台
265 | // batch.draw(texture, 0, 0, 960, 540);
266 | batch.end();
267 | Gdx.gl20.glEnable(GL20.GL_DEPTH_TEST);
268 | Gdx.gl20.glEnable(GL20.GL_TEXTURE);
269 | Gdx.gl20.glEnable(GL20.GL_TEXTURE_2D);
270 | // Gdx.gl20.glEnable(GL20.GL_LINE_SMOOTH);//54wall old
271 | Gdx.gl20.glEnable(GL20.GL_LINE_LOOP);// new
272 | Gdx.gl20.glDepthFunc(GL20.GL_LEQUAL);
273 | Gdx.gl20.glClearDepthf(1.0F);
274 | camera.update(true);
275 | // camera.apply(Gdx.gl20);//54wall old
276 | texture.bind();
277 |
278 | if (mode == Mode.waitForPictureReady) {
279 | /*注意deviceCameraControl.getPictureData()得到的是byte[],可见整体思路就是,
280 | *将Android摄像头得到byte[],然后将byte[]转换为Pixmap,最后将pixmap存为jpg,这样不适用Android端图片保存模式,
281 | *byte[]----Pixmap----jpg
282 | */
283 | if (deviceCameraControl.getPictureData() != null) {
284 | // camera picture was actually takentake Gdx Screenshot
285 | Pixmap screenshotPixmap = getScreenshot(0, 0,
286 | Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), true);
287 | /* 开始报错deviceCameraControl.getPictureData一直未null */
288 | Pixmap cameraPixmap = new Pixmap(
289 | deviceCameraControl.getPictureData(), 0,
290 | deviceCameraControl.getPictureData().length);
291 | merge2Pixmaps(cameraPixmap, screenshotPixmap);
292 | // we could call PixmapIO.writePNG(pngfile, cameraPixmap);
293 | /* 仅保存screenshot,对同一时间的图片进行保存然后进行比较 */
294 | Pixmap screenshotPixmap_test = getScreenshot(0, 0,
295 | Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), true);
296 | FileHandle jpgfile_screenshot = Gdx.files
297 | .external("a_SDK_fail/libGdxSnapshot" + "_" + date
298 | + "_screenshot.jpg");
299 | deviceCameraControl.saveAsJpeg(jpgfile_screenshot,
300 | screenshotPixmap_test);
301 | /* 仅保存cameraPixma,对同一时间的图片进行保存然后进行比较 */
302 | Pixmap cameraPixmap_test = new Pixmap(
303 | deviceCameraControl.getPictureData(), 0,
304 | deviceCameraControl.getPictureData().length);
305 | FileHandle jpgfile_cameraPixmap = Gdx.files
306 | .external("a_SDK_fail/libGdxSnapshot" + "_" + date
307 | + "_camera.jpg");
308 | deviceCameraControl.saveAsJpeg(jpgfile_cameraPixmap,
309 | cameraPixmap_test);
310 | /* 保存混合之后的相片 */
311 | FileHandle jpgfile = Gdx.files
312 | .external("a_SDK_fail/libGdxSnapshot" + "_" + date
313 | + ".jpg");
314 | Gdx.app.log("FileHandle", date);
315 | time_1 = System.currentTimeMillis();
316 | deviceCameraControl.saveAsJpeg(jpgfile, cameraPixmap);
317 | time_2 = System.currentTimeMillis();
318 | /* 可以得到35830ms=35s,所以非常忙,导致Mode非常缓慢的回到Mode.normal */
319 | Gdx.app.log("cost", String.valueOf(time_2 - time_1));
320 | deviceCameraControl.stopPreviewAsync();
321 | /* 保存文件后,mode回到normal继续render循环,所以中间停顿的其实是卡住了?! */
322 | mode = Mode.normal;
323 |
324 | }
325 | }
326 | /* 这个log将会一直出现,所以render其实是一直在执行 */
327 | // Gdx.app.log("mode", String.valueOf(mode));
328 | // Gdx.app.log("mode", String.valueOf(i_render++));
329 | }
330 | /* 随手加一个log是很重要的 */
331 | public void takePicture4render() {
332 | /*
333 | * 进入app后,手按住屏幕不放,才能进入预览模式,放开就直接拍照了
334 | * input.isTouched(1)可能与button点击存在冲突,所以必须屏蔽
335 | */
336 | // if (Gdx.input.isTouched(1)) {
337 | //
338 | // mode = Mode.normal;
339 | // Gdx.app.log("doube", String.valueOf(mode));
340 | // }
341 | //
342 | //
343 | // if (Gdx.input.isTouched()) {
344 | // if (mode == Mode.normal) {
345 | // mode = Mode.prepare;
346 | // if (deviceCameraControl != null) {
347 | // deviceCameraControl.prepareCameraAsync();
348 | // }
349 | // }
350 | // } else {
351 | // // touch removed
352 | // if (mode == Mode.preview) {
353 | // mode = Mode.takePicture;
354 | // }
355 | // }
356 |
357 | /* 我想让摄像头一直处于预览状态 */
358 | // if (deviceCameraControl != null) {
359 | // deviceCameraControl.prepareCameraAsync();
360 | // }
361 |
362 | /* 仅跟进入预览后直接进入拍照模式 */
363 | if (mode == Mode.preview) {
364 | mode = Mode.takePicture;
365 | }
366 |
367 | // Gdx.gl20.glHint(GL20.GL_PERSPECTIVE_CORRECTION_HINT,
368 | // GL20.GL_NICEST);//old 54wall
369 | Gdx.gl20.glHint(GL20.GL_GENERATE_MIPMAP_HINT, GL20.GL_NICEST);
370 | if (mode == Mode.takePicture) {
371 | /* 没有清屏,摄像头的预览功能就没有 */
372 | Gdx.gl20.glClearColor(0f, 0.0f, 0.0f, 0.0f);
373 | batch.begin();
374 | stage.act(); // 更新舞台逻辑
375 | button.draw(batch, 1.0F);// 仅绘制actor
376 | stage.draw();// 绘制舞台
377 | batch.draw(texture, 0, 0, 960, 540);
378 | batch.end();
379 |
380 | if (deviceCameraControl != null) {
381 | deviceCameraControl.takePicture();
382 |
383 | }
384 | mode = Mode.waitForPictureReady;
385 | } else if (mode == Mode.waitForPictureReady) {
386 | Gdx.gl20.glClearColor(0.0f, 0f, 0.0f, 0.0f);
387 | batch.begin();
388 | stage.act();
389 | button.draw(batch, 1.0F);
390 | stage.draw();
391 | batch.draw(texture, 0, 0, 960, 540);
392 | batch.end();
393 |
394 | } else if (mode == Mode.prepare) {
395 | Gdx.gl20.glClearColor(0.0f, 0.0f, 0f, 0.0f);
396 | batch.begin();
397 | stage.act();
398 | button.draw(batch, 1.0F);
399 | stage.draw();
400 | batch.draw(texture, 0, 0, 960, 540);
401 | batch.end();
402 | if (deviceCameraControl != null) {
403 | if (deviceCameraControl.isReady()) {
404 | deviceCameraControl.startPreviewAsync();
405 | mode = Mode.preview;
406 | }
407 | }
408 | } else if (mode == Mode.preview) {
409 | Gdx.gl20.glClearColor(0.0f, 0.0f, 0.0f, 0f);
410 | batch.begin();
411 | stage.act();
412 | button.draw(batch, 1.0F);
413 | stage.draw();
414 | batch.draw(texture, 0, 0, 960, 540);
415 | batch.end();
416 | } else {
417 | /* mode = normal */
418 | Gdx.gl20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
419 | batch.begin();
420 | stage.act();
421 | button.draw(batch, 1.0F);
422 | stage.draw();
423 | batch.draw(texture, 0, 0, 960, 540);
424 | batch.end();
425 | }
426 | Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
427 |
428 | batch.begin();
429 | stage.act();
430 | button.draw(batch, 1.0F);
431 | stage.draw();
432 | batch.draw(texture, 0, 0, 960, 540);
433 | batch.end();
434 |
435 | Gdx.gl20.glEnable(GL20.GL_DEPTH_TEST);
436 | Gdx.gl20.glEnable(GL20.GL_TEXTURE);
437 | Gdx.gl20.glEnable(GL20.GL_TEXTURE_2D);
438 | // Gdx.gl20.glEnable(GL20.GL_LINE_SMOOTH);//54wall old
439 | Gdx.gl20.glEnable(GL20.GL_LINE_LOOP);// new
440 | Gdx.gl20.glDepthFunc(GL20.GL_LEQUAL);
441 | Gdx.gl20.glClearDepthf(1.0F);
442 | camera.update(true);
443 | // camera.apply(Gdx.gl20);//54wall old
444 | texture.bind();
445 | for (int i = 0; i < 6; i++) {
446 | /*
447 | * 可以尝试直接使用上述代码,对一张渲染的图片进行剪切,或者使用三角形代替这里这么多的网格,然后看效果
448 | * http://blog.sina.com.cn/s/blog_940dd50a0101fl4s.html
449 | */
450 | // mesh[i].render( GL20.GL_TRIANGLE_FAN, 0 ,4);//54wall old
451 | // ShaderProgram shader = new ShaderProgram(1 1);//原来的数目一样,不知道会不会影响
452 | // ShaderProgram shader = new ShaderProgram(String.valueOf(i),
453 | // String.valueOf(i+1));//54new
454 | // mesh[i].render(shader, GL20.GL_TRIANGLE_FAN, 0, 4);//54new
455 | }
456 | if (mode == Mode.waitForPictureReady) {
457 | /*
458 | * 注意deviceCameraControl.getPictureData()得到的是byte[],可见整体思路就是,
459 | * 将Android摄像头得到byte[],然后
460 | * 将byte[]转换为Pixmap,最后将pixmap存为jpg,这样不适用Android端图片保存模式,
461 | * byte[]----Pixmap----jpg
462 | */
463 | if (deviceCameraControl.getPictureData() != null) {
464 | // camera picture was actually takentake Gdx Screenshot
465 | Pixmap screenshotPixmap = getScreenshot(0, 0,
466 | Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), true);
467 |
468 | Pixmap cameraPixmap = new Pixmap(
469 | deviceCameraControl.getPictureData(), 0,
470 | deviceCameraControl.getPictureData().length);
471 |
472 | merge2Pixmaps(cameraPixmap, screenshotPixmap);
473 | // we could call PixmapIO.writePNG(pngfile, cameraPixmap);
474 | /* 现在有一个问题就是每次都是拍照两次,才有一张图片 */
475 | FileHandle jpgfile = Gdx.files
476 | .external("a_SDK_fail/libGdxSnapshot" + "_" + date
477 | + ".jpg");
478 | Gdx.app.log("FileHandle", date);
479 | time_1 = System.currentTimeMillis();
480 | deviceCameraControl.saveAsJpeg(jpgfile, cameraPixmap);
481 |
482 | time_2 = System.currentTimeMillis();
483 | /* 可以得到35830ms=35s,所以非常忙,导致Mode非常缓慢的回到Mode.normal */
484 | Gdx.app.log("cost", String.valueOf(time_2 - time_1));
485 | deviceCameraControl.stopPreviewAsync();
486 | /* 保存文件后,mode回到normal继续render循环,所以中间停顿的其实是卡住了?! */
487 | mode = Mode.normal;
488 |
489 | }
490 | }
491 | /* 这个log将会一直出现 */
492 | Gdx.app.log("mode", String.valueOf(mode));
493 | }
494 |
495 | /* 注意截图与Android设备摄像传回的图像整合时并非按我所看的视角进行 */
496 | private Pixmap merge2Pixmaps(Pixmap mainPixmap, Pixmap overlayedPixmap) {
497 | // merge to data and Gdx screen shot - but fix Aspect Ratio issues
498 | // between the screen and the camera
499 | Pixmap.setFilter(Filter.BiLinear);
500 | float mainPixmapAR = (float) mainPixmap.getWidth()
501 | / mainPixmap.getHeight();
502 | float overlayedPixmapAR = (float) overlayedPixmap.getWidth()
503 | / overlayedPixmap.getHeight();
504 | if (overlayedPixmapAR < mainPixmapAR) {
505 | int overlayNewWidth = (int) (((float) mainPixmap.getHeight() / overlayedPixmap
506 | .getHeight()) * overlayedPixmap.getWidth());
507 | int overlayStartX = (mainPixmap.getWidth() - overlayNewWidth) / 2;
508 | // Overlaying pixmaps
509 | mainPixmap.drawPixmap(overlayedPixmap, 0, 0,
510 | overlayedPixmap.getWidth(), overlayedPixmap.getHeight(),
511 | overlayStartX, 0, overlayNewWidth, mainPixmap.getHeight());
512 | } else {
513 | int overlayNewHeight = (int) (((float) mainPixmap.getWidth() / overlayedPixmap
514 | .getWidth()) * overlayedPixmap.getHeight());
515 | int overlayStartY = (mainPixmap.getHeight() - overlayNewHeight) / 2;
516 | // Overlaying pixmaps
517 | mainPixmap.drawPixmap(overlayedPixmap, 0, 0,
518 | overlayedPixmap.getWidth(), overlayedPixmap.getHeight(), 0,
519 | overlayStartY, mainPixmap.getWidth(), overlayNewHeight);
520 | }
521 | return mainPixmap;
522 | }
523 |
524 | public Pixmap getScreenshot(int x, int y, int w, int h, boolean flipY) {
525 |
526 | Gdx.gl.glPixelStorei(GL20.GL_PACK_ALIGNMENT, 1);
527 | final Pixmap pixmap = new Pixmap(w, h, Format.RGBA8888);
528 | ByteBuffer pixels = pixmap.getPixels();
529 | Gdx.gl.glReadPixels(x, y, w, h, GL20.GL_RGBA, GL20.GL_UNSIGNED_BYTE,
530 | pixels);
531 |
532 | final int numBytes = w * h * 4;
533 | byte[] lines = new byte[numBytes];
534 | if (flipY) {
535 | final int numBytesPerLine = w * 4;
536 | for (int i = 0; i < h; i++) {
537 | pixels.position((h - i - 1) * numBytesPerLine);
538 | pixels.get(lines, i * numBytesPerLine, numBytesPerLine);
539 | }
540 | pixels.clear();
541 | pixels.put(lines);
542 | } else {
543 | pixels.clear();
544 | pixels.get(lines);
545 | }
546 |
547 | return pixmap;
548 | }
549 |
550 | @Override
551 | public void resize(int width, int height) {
552 | camera = new PerspectiveCamera(67.0f, 2.0f * width / height, 2.0f);
553 | camera.far = 100.0f;
554 | camera.near = 0.1f;
555 | camera.position.set(2.0f, 2.0f, 2.0f);
556 | camera.lookAt(0.0f, 0.0f, 0.0f);
557 |
558 | }
559 |
560 | @Override
561 | public void pause() {
562 | }
563 |
564 | @Override
565 | public void resume() {
566 | }
567 |
568 | ClickListener preview_on = new ClickListener() {
569 |
570 | @Override
571 | public void clicked(InputEvent event, float x, float y) {
572 | Gdx.app.log("preview_on", "preview_on按钮被点击了");
573 | if (mode == Mode.waitForPictureReady) {
574 | mode = Mode.normal;
575 | }
576 | if (mode == Mode.normal) {
577 | mode = Mode.prepare;
578 | if (deviceCameraControl != null) {
579 | deviceCameraControl.prepareCameraAsync();
580 | }
581 | }
582 | }
583 |
584 | };
585 |
586 |
587 | ClickListener actor_move = new ClickListener() {
588 |
589 | @Override
590 | public void clicked(InputEvent event, float x, float y) {
591 | firstActor.setX(firstActor.getX() + 55);
592 | Gdx.app.log("actor_move", "actor_move按钮被点击了");
593 | }
594 |
595 | };
596 |
597 | ClickListener preview_on_1 = new ClickListener() {
598 |
599 | @Override
600 | public void clicked(InputEvent event, float x, float y) {
601 | Gdx.app.log("preview_on_1", "preview_on_1按钮被点击了");
602 | if (mode == Mode.preview) {
603 | mode = Mode.takePicture;
604 | }
605 |
606 | }
607 |
608 | };
609 |
610 | ClickListener preview_off = new ClickListener() {
611 | @Override
612 | public void clicked(InputEvent event, float x, float y) {
613 | Gdx.app.log("preview_on", "1按钮被点击了");
614 | /*
615 | * 不等输入,直接写mode =
616 | * Mode.takePicture;相当于deviceCameraControl.prepareCameraAsync
617 | * ();没有写,会报空指针 java.lang.NullPointerException at
618 | * com.mygdx.game0606.android.AndroidDeviceCameraController
619 | * .takePicture(AndroidDeviceCameraController.java:122)
620 | */
621 |
622 | /*
623 | * takePicture4render不能写在这里,因为batch.draw(texture, 0, 0, 960,
624 | * 540);应该在render中完成
625 | */
626 | // takePicture4render();
627 | /*
628 | * 增加下面语句后可以完成点击按钮进行拍照,关键就是让Mode进行一个完整的循环
629 | * 程序循环成Mode.normal时,屏幕再次回到黑色,才表示循环完成一次
630 | */
631 | if (mode == Mode.waitForPictureReady) {
632 | mode = Mode.normal;
633 | }
634 |
635 | if (mode == Mode.normal) {
636 | mode = Mode.prepare;
637 | if (deviceCameraControl != null) {
638 | /*
639 | * 首先button的点击可能与Gdx.input.isTouched()输入检测有冲突,然后,
640 | * 通过仅屏蔽deviceCameraControl.prepareCameraAsync();
641 | * 发现代码在render后
642 | * ,button依然有效,但是prepareCameraAsync后button失效,确认代码范围
643 | */
644 | deviceCameraControl.prepareCameraAsync();
645 | }
646 | }
647 | /* Mode.prepare之后不是Mode.preview,所以不能直接接入下边 */
648 | // if (mode == Mode.preview) {
649 | // mode = Mode.takePicture;
650 | // }
651 |
652 | }
653 | };
654 |
655 | }
656 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 完整代码已上传github,https://github.com/54wall/LibgdxAndroidCamera
2 |
3 | ## 开发背景 ##
4 |
5 | 简单介绍下本文主要介绍了下如何libGDX调用android摄像头的步骤,内容非原创。通过在Libgdx中调用摄像头,可以实现伪AR游戏:一个是抓幽灵的游戏ChaseWhisplyProject,来自
6 | 
7 |
8 | 另外一个beyondar,来自
9 |
10 | 
11 |
12 | 当然,上边两个全部在Android内实现的,而非在libgdx中实现,感谢Github,在libGDX的介绍中,有达人分享了他使用libGDX调用android摄像头的实例,他在libGDX中调用摄像头的目的简单来说就是AR,使用者可以通过APP看到设备背后的路面,或者和真实世界有交互,就像PokemonGO一样,当然全部的这些也需要算法支持。但是时间是2013年,我拷贝下来,进行了微调,发现是可以实现的,鉴于目前网络上还真没有许多的实例说明如何在LibGDX中调用android摄像头,我搜索libgdx camera 大部分给我的结果都是libgdx中的镜头,就是跟随演员的镜头,而不是设备摄像头,这里也对这个实例进行一个记录和补充,以及简单的实现。
13 |
14 | wiki地址:[https://github.com/libgdx/libgdx/wiki/Integrating-libgdx-and-the-device-camera](https://github.com/libgdx/libgdx/wiki/Integrating-libgdx-and-the-device-camera)
15 |
16 | 下面我也是基于这篇文章进行翻译,顺序当然有所改变,还有原代码中有包含一个类似初始页面的SplashActivity的我没有实现,目前还没有去了解libGDX的三维编程,代码的源码已上传至GitHub,再好的文字也比不上源码。
17 | 完整代码已上传github,https://github.com/54wall/LibgdxAndroidCamera
18 | **libGDX中到底是如何实现调用摄像头**
19 |
20 | 很简单,就是在一个透明的画布上绘制libGDX的舞台演员,在画布的后边放置摄像头的预览画面。而文章主要解决的问题就是如何显示摄像头预览画面,和如何调用摄像头。
21 |
22 | **如何显示摄像头预览画面**
23 |
24 | 我们知道,libGDX的代码主要全部在core项目中,其他各个平台的代码都是经过一个简单的代码启动启动然后,剩下的就去调用core项目中的代码,首先在libGDX初始化时,要进行一定的设置,才能让摄像头的预览画面显示在libGDX框架生成的app中,进入android项目组,修改AndroidLauncher.class代码如下
25 |
26 | ```java
27 | AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration();
28 | cfg.r = 8;
29 | cfg.g = 8;
30 | cfg.b = 8;
31 | cfg.a = 8;
32 | DeviceCameraControl cameraControl = new AndroidDeviceCameraController(this);
33 | initialize(new MyGdxGame0606(cameraControl), cfg);
34 | ```
35 |
36 | 你可以点击进入AndroidApplicationConfiguration去看看r,g,b,a原来数值如下
37 |
38 | ```java
39 | /** number of bits per color channel **/
40 | public int r = 5, g = 6, b = 5, a = 0;
41 | ```
42 |
43 | rgba的具体值指的是每种颜色的比特位数,这里改为8位,大概的意思就是每种颜色深度为8位,也就是2的8次幂,也就是256,和photoshop中意义一样。这么设置的原因是为了libGDX中的画布的后边能够正常的显示android的摄像头,不然颜色和在android上调用摄像头有出入,色彩不会同样的丰富。
44 |
45 | 同样在AndroidLauncher.class中,将OpenGL surface 模式设置成TRANSLUCENT
46 |
47 |
48 | ```java
49 | if (graphics.getView() instanceof SurfaceView) {
50 | SurfaceView glView = (SurfaceView) graphics.getView();
51 | // force alpha channel - I'm not sure we need this as the GL surface
52 | // is already using alpha channel
53 | glView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
54 | }
55 | ```
56 |
57 | 然后是,在AndroidLauncher.class新建一个post方法,用来帮助唤起一些异步线程
58 |
59 | ```java
60 | public void post(Runnable r) {
61 | handler.post(r);
62 | }
63 | ```
64 |
65 | 以上就是AndroidLauncher.class所要完成的全部内容。
66 | **如何让屏幕透明**
67 |
68 | 很简单,在core项目中MyGdxGame0606.class主类中的render()渲染方法中,要注意使用glClearColor()清屏时,参数的选择必须全部是0,这样相机预览的画面才会显示在render画面的后边
69 |
70 | ```java
71 | Gdx.gl20.glClearColor(0f, 0.0f, 0.0f, 0.0f);
72 | ```
73 |
74 | **清屏准备完毕,现在就是要调用android摄像头的时候到了**
75 |
76 | 首先了解一下,把大象装冰箱中总共分几步?对于调用android摄像头的步骤则可以分如下几部?Android相机有特别的工作顺序必须遵守,通过application的callbacks回调函数能管理相机的状态,机器的工作状态将由AndroidDeviceCameraController.class进行管理(desktop没有实现,Android已实现)。
77 | 相机的工作状态一次是 Ready -> Preview -> autoFocusing -> ShutterCalled -> Raw PictureData -> Postview PictureData -> Jpeg PictureData -> Ready (可以做一个表格)
78 | 本实例代码实现的顺序也可以概括为 Ready -> Preview -> autoFocusing -> Jpeg PictureData -> Ready
79 | **新建AndroidDeviceCameraController**
80 |
81 | 在core项目中,新建一个DeviceCameraController类,而为了配合core中DeviceCameraControl,在android项目中,新建一个AndroidDeviceCameraController 类,来控制设备的摄像头,它要继承DeviceCameraControl,同时还要实现Camera.PictureCallback:(android.hardware.Camera.PictureCallback)Camera.AutoFocusCallback(android.hardware.Camera.AutoFocusCallback),共计三个接口,来实现android摄像头从准备到拍摄的过程。
82 |
83 | ```java
84 | public class AndroidDeviceCameraController implements DeviceCameraControl, Camera.PictureCallback, Camera.AutoFocusCallback {
85 | }
86 | ```
87 | AndroidDeviceCameraController 新建后,逐步实现摄像头该有的各个功能。
88 | **1.准备显示预览信息的CameraSurface**
89 |
90 | 我们产生一个CameraSurface类来负责管理摄像头和它收集的图像,这里我和android摄像相关的代码一致
91 |
92 | ```java
93 | public class CameraSurface extends SurfaceView implements SurfaceHolder.Callback {
94 | private Camera camera;
95 | public CameraSurface( Context context ) {
96 | super( context );
97 | // We're implementing the Callback interface and want to get notified
98 | // about certain surface events.
99 | getHolder().addCallback( this );
100 | // We're changing the surface to a PUSH surface, meaning we're receiving
101 | // all buffer data from another component - the camera, in this case.
102 | getHolder().setType( SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS );
103 | }
104 | public void surfaceCreated( SurfaceHolder holder ) {
105 | // Once the surface is created, simply open a handle to the camera hardware.
106 | camera = Camera.open();
107 | }
108 | public void surfaceChanged( SurfaceHolder holder, int format, int width, int height ) {
109 | // This method is called when the surface changes, e.g. when it's size is set.
110 | // We use the opportunity to initialize the camera preview display dimensions.
111 | Camera.Parameters p = camera.getParameters();
112 | p.setPreviewSize( width, height );
113 | camera.setParameters( p );
114 | // We also assign the preview display to this surface...
115 | try {
116 | camera.setPreviewDisplay( holder );
117 | } catch( IOException e ) {
118 | e.printStackTrace();
119 | }
120 | }
121 | public void surfaceDestroyed( SurfaceHolder holder ) {
122 | // Once the surface gets destroyed, we stop the preview mode and release
123 | // the whole camera since we no longer need it.
124 | camera.stopPreview();
125 | camera.release();
126 | camera = null;
127 | }
128 | public Camera getCamera() {
129 | return camera;
130 | }
131 | }
132 | ```
133 |
134 | **2.在android项目中增加相机预览视图**
135 |
136 | 在android项目的AndroidDeviceController类,使用activity.addContentView,直接将cameraSurface显示在android设备的屏幕上
137 |
138 | ```java
139 | @Override
140 | public void prepareCamera() {
141 | if (cameraSurface == null) {
142 | cameraSurface = new CameraSurface(activity);
143 | }
144 | activity.addContentView( cameraSurface, new LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT ) );
145 | }
146 | ```
147 |
148 | ```java
149 | @Override
150 | public synchronized void prepareCamera() {
151 | if (cameraSurface == null) {
152 | cameraSurface = new CameraSurface(activity);
153 | }
154 | FrameLayout.LayoutParams params = new FrameLayout.LayoutParams (680,680);
155 | params.rightMargin=150;//可以通过设置rightMargin控制组件的实际位置
156 | params.leftMargin=200;//可以通过设置rightMargin控制组件的实际位置
157 | params.topMargin=100;
158 | activity.addContentView(cameraSurface, params);
159 |
160 |
161 | }
162 | ```
163 |
164 | prepareCamera方法应该在libgdx渲染过程中异步调用
165 |
166 | ```java
167 | @Override
168 | public void prepareCameraAsync() {
169 | Runnable r = new Runnable() {
170 | public void run() {
171 | prepareCamera();
172 | }
173 | };
174 | activity.post(r);
175 | }
176 |
177 | @Override
178 | public void prepareCameraAsync() {
179 | Runnable r = new Runnable() {
180 | public void run() {
181 | prepareCamera();
182 | }
183 | };
184 | activity.post(r);
185 | }
186 | ```
187 |
188 | 当CameraSurface和camera 对象准备好了的时候(通过检测cameraSurface!=null && cameraSurface.getCamera() != null),就可以让相机由准备状态进入预览模式
189 |
190 | ```java
191 | @Override
192 | public boolean isReady() {
193 | if (cameraSurface!=null && cameraSurface.getCamera() != null) {
194 | return true;
195 | }
196 | return false;
197 | }
198 | ```
199 |
200 | ```java
201 | @Override
202 | public boolean isReady() {
203 | if (cameraSurface != null && cameraSurface.getCamera() != null) {
204 | return true;
205 | }
206 | return false;
207 | }
208 | ```
209 |
210 | 异步调用开启预览
211 |
212 | ```java
213 | @Override
214 | public synchronized void startPreviewAsync() {
215 | Runnable r = new Runnable() {
216 | public void run() {
217 | startPreview();
218 | }
219 | };
220 | activity.post(r);
221 | }
222 | @Override
223 | public synchronized void startPreview() {
224 | // ...and start previewing. From now on, the camera keeps pushing preview
225 | // images to the surface.
226 | if (cameraSurface != null && cameraSurface.getCamera() != null) {
227 | cameraSurface.getCamera().startPreview();
228 | }
229 | }
230 | ```
231 |
232 | **3.由预览模式进行拍照**
233 |
234 | 拍照前还要AndroidDeviceCameraController类设置下相机合适的参数
235 |
236 |
237 | ```java
238 | public void setCameraParametersForPicture(Camera camera) {
239 | // Before we take the picture - we make sure all camera parameters are as we like them
240 | // Use max resolution and auto focus
241 | Camera.Parameters p = camera.getParameters();
242 | List supportedSizes = p.getSupportedPictureSizes();
243 | int maxSupportedWidth = -1;
244 | int maxSupportedHeight = -1;
245 | for (Camera.Size size : supportedSizes) {
246 | if (size.width > maxSupportedWidth) {
247 | maxSupportedWidth = size.width;
248 | maxSupportedHeight = size.height;
249 | }
250 | }
251 | p.setPictureSize(maxSupportedWidth, maxSupportedHeight);
252 | p.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
253 | camera.setParameters( p );
254 | }
255 | ```
256 |
257 | 接下来,我们将通过设置相机的参数,设置聚焦为自动模式,
258 |
259 | ```java
260 | @Override
261 | public synchronized void takePicture() {
262 | // the user request to take a picture - start the process by requesting focus
263 | setCameraParametersForPicture(cameraSurface.getCamera());
264 | cameraSurface.getCamera().autoFocus(this);
265 | }
266 | ```
267 |
268 | 当聚焦完成后,我们就要拍照了,仅仅实现JPG回调实现
269 |
270 |
271 | ```java
272 | @Override
273 | public synchronized void onAutoFocus(boolean success, Camera camera) {
274 | // Focus process finished, we now have focus (or not)
275 | if (success) {
276 | if (camera != null) {
277 | camera.stopPreview();
278 | // We now have focus take the actual picture
279 | camera.takePicture(null, null, null, this);
280 | }
281 | }
282 | }
283 | @Override
284 | public synchronized void onPictureTaken(byte[] pictureData, Camera camera) {
285 | this.pictureData = pictureData;
286 | }
287 |
288 | @Override
289 | public synchronized void onAutoFocus(boolean success, Camera camera) {
290 | // Focus process finished, we now have focus (or not)
291 | if (success) {
292 | if (camera != null) {
293 | camera.stopPreview();
294 | /*增加三个回调函数shutterCallback, rawPictureCallback, jpegPictureCallback后,可以进行拍照,并且成功保存*/
295 | // We now have focus take the actual picture
296 | camera.takePicture(shutterCallback, rawPictureCallback, jpegPictureCallback);//54wall
297 | camera.startPreview();
298 |
299 | }
300 | }
301 | }
302 |
303 | @Override
304 | public synchronized void onPictureTaken(byte[] pictureData, Camera camera) {
305 | // We got the picture data - keep it
306 | this.pictureData = pictureData;
307 | }
308 |
309 | ShutterCallback shutterCallback = new ShutterCallback() {
310 | @Override
311 | public void onShutter() {
312 | }
313 | };
314 |
315 | PictureCallback rawPictureCallback = new PictureCallback() {
316 | @Override
317 | public void onPictureTaken(byte[] arg0, Camera arg1) {
318 |
319 | }
320 | };
321 |
322 | PictureCallback jpegPictureCallback = new PictureCallback() {
323 | @Override
324 | public void onPictureTaken(byte[] arg0, Camera arg1) {
325 | /*可以在Android项目中中生成图片*/
326 | // String fileName = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
327 | // .toString()
328 | // + File.separator
329 | // + "PicTest_" + System.currentTimeMillis() + ".jpg";
330 | // File file = new File(fileName);
331 | // if (!file.getParentFile().exists()) {
332 | // file.getParentFile().mkdir();
333 | // }
334 | //
335 | // try {
336 | // BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
337 | // bos.write(arg0);
338 | // bos.flush();
339 | // bos.close();
340 | //
341 | // } catch (Exception e) {
342 | //
343 | // }
344 | pictureData=arg0;
345 |
346 | };
347 | };
348 | ```
349 | 以上就是拍照的具体步骤,之后照片完成后,需要将图像数据进行保存到存储器上
350 | 拍照的具体功能实现了,为了在libgdx中能够看到摄像头,当然需要在实现ApplicationListener的主类的render()进行设置了,我这里设置了三个按钮,功能分别是开启相机,进行拍摄,和一个控制人物移动的按钮(算是证明是在libgdx框架内部的)。
351 | 原代码时触控进入相机预览,松开则进行拍照,我开始还没太理解,render中因为涉及到相机的功能切换,所以在libgdx主类中定义了相机的这几种状态
352 | ```java
353 | public enum Mode {
354 | normal, prepare, preview, takePicture, waitForPictureReady,
355 | },
356 | ```
357 | render()中的代码非常长,不过就是在相机的各个状态中切换,具体代码如下:
358 | ```java
359 | @Override
360 | public void render() {
361 | // Gdx.gl20.glClearColor(0.0f, 0f, 0.0f, 0.0f);//黑
362 | // Gdx.gl.glClearColor(1, 1, 1, 1);//背景为白色
363 | Gdx.gl.glClearColor(0.57f, 0.40f, 0.55f, 1.0f);// 紫色
364 | Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);// 清屏
365 | render_preview();
366 |
367 | }
368 |
369 |
370 | public void render_preview() {
371 | /* 我已经将preview变为takePicture状态移动到click中,实现先预览再拍照,这样便于理解相机的运行步骤 */
372 | Gdx.gl20.glHint(GL20.GL_GENERATE_MIPMAP_HINT, GL20.GL_NICEST);
373 | if (mode == Mode.takePicture) {
374 | Gdx.gl20.glClearColor(0f, 0.0f, 0.0f, 0.0f);
375 | if (deviceCameraControl != null) {
376 | deviceCameraControl.takePicture();
377 | }
378 | mode = Mode.waitForPictureReady;
379 | } else if (mode == Mode.waitForPictureReady) {
380 | Gdx.gl20.glClearColor(0.0f, 0f, 0.0f, 0.0f);
381 | } else if (mode == Mode.prepare) {
382 | Gdx.gl20.glClearColor(0.0f, 0.0f, 0f, 0.6f);
383 | if (deviceCameraControl != null) {
384 | if (deviceCameraControl.isReady()) {
385 | deviceCameraControl.startPreviewAsync();
386 | mode = Mode.preview;
387 | }
388 | }
389 | } else if (mode == Mode.preview) {
390 | Gdx.gl20.glClearColor(0.0f, 0.0f, 0.0f, 0f);
391 | } else {
392 | /* mode = normal */
393 | Gdx.gl20.glClearColor(0.0f, 0.0f, 0.6f, 1.0f);
394 |
395 | }
396 | Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
397 | /* 下边放到texture.bind();时效果一致 */
398 | batch.begin();
399 | stage.act(); // 更新舞台逻辑
400 | batch.draw(texture, 0, 0, 3f*texture.getWidth(), 3f*texture.getHeight());
401 | Gdx.app.log("", String.valueOf(texture.getWidth()));
402 | //先绘制的就先出现,所以演员在texture上边,而不是被覆盖
403 | //batch.draw(actorTexture, firstActor.getX(), firstActor.getY());//原大小
404 | batch.draw(actorTexture, firstActor.getX(), firstActor.getY(),4*actorTexture.getWidth(),4*actorTexture.getWidth());//可控制绘制图像大小
405 | button_move.draw(batch, 1.0f);
406 | stage.draw();// 绘制舞台
407 | batch.end();
408 | Gdx.gl20.glEnable(GL20.GL_DEPTH_TEST);
409 | Gdx.gl20.glEnable(GL20.GL_TEXTURE);
410 | Gdx.gl20.glEnable(GL20.GL_TEXTURE_2D);
411 | // Gdx.gl20.glEnable(GL20.GL_LINE_SMOOTH);//old
412 | Gdx.gl20.glEnable(GL20.GL_LINE_LOOP);//54wall
413 | Gdx.gl20.glDepthFunc(GL20.GL_LEQUAL);
414 | Gdx.gl20.glClearDepthf(1.0F);
415 | camera.update(true);
416 | // camera.apply(Gdx.gl20);//old
417 | texture.bind();
418 |
419 | if (mode == Mode.waitForPictureReady) {
420 | /*注意deviceCameraControl.getPictureData()得到的是byte[],可见整体思路就是,
421 | *将Android摄像头得到byte[],然后将byte[]转换为Pixmap,最后将pixmap存为jpg,这样不适用Android端图片保存模式,
422 | *byte[]----Pixmap----jpg
423 | */
424 | if (deviceCameraControl.getPictureData() != null) {
425 | // camera picture was actually takentake Gdx Screenshot
426 | Pixmap screenshotPixmap = getScreenshot(0, 0,
427 | Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), true);
428 | Pixmap cameraPixmap = new Pixmap(
429 | deviceCameraControl.getPictureData(), 0,
430 | deviceCameraControl.getPictureData().length);
431 | merge2Pixmaps(cameraPixmap, screenshotPixmap);
432 | // we could call PixmapIO.writePNG(pngfile, cameraPixmap);
433 | //仅保存screenshot,对同一时间的图片进行保存然后进行比较
434 | Pixmap screenshotPixmap_test = getScreenshot(0, 0,
435 | Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), true);
436 | FileHandle jpgfile_screenshot = Gdx.files
437 | .external("a_SDK_fail/libGdxSnapshot" + "_" + date
438 | + "_screenshot.jpg");
439 | deviceCameraControl.saveAsJpeg(jpgfile_screenshot,
440 | screenshotPixmap_test);
441 | //仅保存cameraPixma,对同一时间的图片进行保存然后进行比较
442 | Pixmap cameraPixmap_test = new Pixmap(
443 | deviceCameraControl.getPictureData(), 0,
444 | deviceCameraControl.getPictureData().length);
445 | FileHandle jpgfile_cameraPixmap = Gdx.files
446 | .external("a_SDK_fail/libGdxSnapshot" + "_" + date
447 | + "_camera.jpg");
448 | deviceCameraControl.saveAsJpeg(jpgfile_cameraPixmap,
449 | cameraPixmap_test);
450 | //保存混合之后的相片
451 | FileHandle jpgfile = Gdx.files
452 | .external("a_SDK_fail/libGdxSnapshot" + "_" + date
453 | + ".jpg");
454 | Gdx.app.log("FileHandle", date);
455 | time_1 = System.currentTimeMillis();
456 | deviceCameraControl.saveAsJpeg(jpgfile, cameraPixmap);
457 | time_2 = System.currentTimeMillis();
458 | //可以得到35830ms=35s,所以非常忙,导致Mode非常缓慢的回到Mode.normal
459 | Gdx.app.log("cost", String.valueOf(time_2 - time_1));
460 | deviceCameraControl.stopPreviewAsync();
461 | //保存文件后,mode回到normal继续render循环,所以中间停顿和logcat长时间未动的其实是卡住了Org
462 | mode = Mode.normal;
463 |
464 | }
465 | }
466 | // 这个log将会一直出现,所以render其实是一直在执行
467 | // Gdx.app.log("mode", String.valueOf(i_render++));
468 | }
469 | ```
470 | **如何实现libgdx端的截图**
471 |
472 | 因为AndroidDeviceCameraController 实现两个接口: Camera.PictureCallback,所以可以直接调用,而deviceCameraControl.getPictureData()的byte[]数据则来自AndroidDeviceCameraController,如下
473 | ```java
474 | @Override
475 | public synchronized byte[] getPictureData() {
476 | // Give to picture data to whom ever requested it
477 | return pictureData;
478 | }
479 | if (deviceCameraControl.getPictureData() != null) { // camera picture was actually taken
480 | Pixmap cameraPixmap = new Pixmap(deviceCameraControl.getPictureData(), 0, deviceCameraControl.getPictureData().length);
481 | }
482 | ```
483 |
484 | 下面是截图的具体操作过程是保存为pixmap,libgdx中保存格式都是pixmap,而非android中的bitmap
485 |
486 | ```java
487 | public Pixmap getScreenshot(int x, int y, int w, int h, boolean flipY) {
488 | Gdx.gl.glPixelStorei(GL10.GL_PACK_ALIGNMENT, 1);
489 | final Pixmap pixmap = new Pixmap(w, h, Format.RGBA8888);
490 | ByteBuffer pixels = pixmap.getPixels();
491 | Gdx.gl.glReadPixels(x, y, w, h, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, pixels);
492 | final int numBytes = w * h * 4;
493 | byte[] lines = new byte[numBytes];
494 | if (flipY) {
495 | final int numBytesPerLine = w * 4;
496 | for (int i = 0; i < h; i++) {
497 | pixels.position((h - i - 1) * numBytesPerLine);
498 | pixels.get(lines, i * numBytesPerLine, numBytesPerLine);
499 | }
500 | pixels.clear();
501 | pixels.put(lines);
502 | } else {
503 | pixels.clear();
504 | pixels.get(lines);
505 | }
506 | return pixmap;
507 | }
508 | ```
509 |
510 | 接下来的操作都是需要消耗大量时间和CPU资源的,首先不应放到UI线程中,应该新开线程去执行,并且最好加一个进度条,在代码示例中,我们并没有那么做,所以屏幕在这个过程中会出现卡死的状况。我这里则直接保存了三分文件,分别是截图,android摄像头的拍摄相片,还有二者混合之后的图片,代码如下
511 |
512 |
513 | ```java
514 | /* 仅保存screenshot,对同一时间的图片进行保存然后进行比较 */
515 | Pixmap screenshotPixmap_test = getScreenshot(0, 0,
516 | Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), true);
517 | FileHandle jpgfile_screenshot = Gdx.files
518 | .external("a_SDK_fail/libGdxSnapshot" + "_" + date
519 | + "_screenshot.jpg");
520 | deviceCameraControl.saveAsJpeg(jpgfile_screenshot,
521 | screenshotPixmap_test);
522 | /* 仅保存cameraPixma,对同一时间的图片进行保存然后进行比较 */
523 | Pixmap cameraPixmap_test = new Pixmap(
524 | deviceCameraControl.getPictureData(), 0,
525 | deviceCameraControl.getPictureData().length);
526 | FileHandle jpgfile_cameraPixmap = Gdx.files
527 | .external("a_SDK_fail/libGdxSnapshot" + "_" + date
528 | + "_camera.jpg");
529 | deviceCameraControl.saveAsJpeg(jpgfile_cameraPixmap,
530 | cameraPixmap_test);
531 | /* 保存混合之后的相片 */
532 | FileHandle jpgfile = Gdx.files
533 | .external("a_SDK_fail/libGdxSnapshot" + "_" + date
534 | + ".jpg");
535 | Gdx.app.log("FileHandle", date);
536 | time_1 = System.currentTimeMillis();
537 | deviceCameraControl.saveAsJpeg(jpgfile, cameraPixmap);
538 | time_2 = System.currentTimeMillis();
539 | /* 可以得到35830ms=35s,所以非常忙,导致Mode非常缓慢的回到Mode.normal */
540 | Gdx.app.log("cost", String.valueOf(time_2 - time_1));
541 | deviceCameraControl.stopPreviewAsync();
542 | ```
543 | **混合两个pixmap**
544 |
545 | 接下来是整合两个PIxmap对象,LibGDX Pixmap对象可以帮助我们实现这个功能,但是因为相机的相片可能有不同的aspect ratio,所以我们也需要分别对待处理
546 |
547 | ```java
548 | private void merge2Pixmaps(Pixmap mainPixmap, Pixmap overlayedPixmap) {
549 | // merge to data and Gdx screen shot - but fix Aspect Ratio issues between the screen and the camera
550 | Pixmap.setFilter(Filter.BiLinear);
551 | float mainPixmapAR = (float)mainPixmap.getWidth() / mainPixmap.getHeight();
552 | float overlayedPixmapAR = (float)overlayedPixmap.getWidth() / overlayedPixmap.getHeight();
553 | if (overlayedPixmapAR < mainPixmapAR) {
554 | int overlayNewWidth = (int)(((float)mainPixmap.getHeight() / overlayedPixmap.getHeight()) * overlayedPixmap.getWidth());
555 | int overlayStartX = (mainPixmap.getWidth() - overlayNewWidth)/2;
556 | mainPixmap.drawPixmap(overlayedPixmap,
557 | 0,
558 | 0,
559 | overlayedPixmap.getWidth(),
560 | overlayedPixmap.getHeight(),
561 | overlayStartX,
562 | 0,
563 | overlayNewWidth,
564 | mainPixmap.getHeight());
565 | } else {
566 | int overlayNewHeight = (int)(((float)mainPixmap.getWidth() / overlayedPixmap.getWidth()) * overlayedPixmap.getHeight());
567 | int overlayStartY = (mainPixmap.getHeight() - overlayNewHeight)/2;
568 | mainPixmap.drawPixmap(overlayedPixmap,
569 | 0,
570 | 0,
571 | overlayedPixmap.getWidth(),
572 | overlayedPixmap.getHeight(),
573 | 0,
574 | overlayStartY,
575 | mainPixmap.getWidth(),
576 | overlayNewHeight);
577 | }
578 | }
579 | ```
580 | **将图片保存为jpg**
581 |
582 | 所以我们选择JPG格式进行保存,一种方式就是使用Android的bitmap类对图片进行jpg格式的保存,这个功能可以在AndroidDeviceController类中实现,因为它是Android特有的功能,所以我们想不用它。
583 | 尽量将大部分代码全部放到libgdx框架中,就是大部分实现的代码要在core中,然而libgdx的pixel格式是RGBA,而bitmap的Pixmap格式是ARGB,所以我们需要一bit一bit的将颜色转换过来
584 |
585 |
586 | ```java
587 | @Override
588 | public void saveAsJpeg(FileHandle jpgfile, Pixmap pixmap) {
589 | FileOutputStream fos;
590 | int x=0,y=0;
591 | int xl=0,yl=0;
592 | try {
593 | Bitmap bmp = Bitmap.createBitmap(pixmap.getWidth(), pixmap.getHeight(), Bitmap.Config.ARGB_8888);
594 | // we need to switch between LibGDX RGBA format to Android ARGB format
595 | for (x=0,xl=pixmap.getWidth(); x ARGB
599 | int RGB = color >> 8;
600 | int A = (color & 0x000000ff) << 24;
601 | int ARGB = A | RGB;
602 | bmp.setPixel(x, y, ARGB);
603 | }
604 | }
605 | // Finished Color format conversion
606 | fos = new FileOutputStream(jpgfile.file());
607 | bmp.compress(CompressFormat.JPEG, 90, fos);
608 | // Finished Comression to JPEG file
609 | fos.close();
610 | } catch (FileNotFoundException e) {
611 | e.printStackTrace();
612 | } catch (IOException e) {
613 | e.printStackTrace();
614 | } catch (IllegalArgumentException e) {
615 | e.printStackTrace();
616 | }
617 | }
618 | ```
619 | **停止预览**
620 |
621 | 在完成保存图片后,我们将停止预览窗口,并且从Activity窗口中移去CameraSurface,我们同样也将停止camera继续想camera surface继续发送preview,我们同样异步执行这些。
622 |
623 |
624 | ```java
625 | @Override
626 | public synchronized void stopPreviewAsync() {
627 | Runnable r = new Runnable() {
628 | public void run() {
629 | stopPreview();
630 | }
631 | };
632 | activity.post(r);
633 | }
634 | @Override
635 | public synchronized void stopPreview() {
636 | // stop previewing.
637 | if (cameraSurface != null) {
638 | if (cameraSurface.getCamera() != null) {
639 | cameraSurface.getCamera().stopPreview();
640 | }
641 | ViewParent parentView = cameraSurface.getParent();
642 | if (parentView instanceof ViewGroup) {
643 | ViewGroup viewGroup = (ViewGroup) parentView;
644 | viewGroup.removeView(cameraSurface);
645 | }
646 | }
647 | }
648 | ```
649 |
650 | 注意在合成两张pixmap也就是混合相机取景和libgdx截图时分辨率有差异。在我们的Pixmaps整合过程中依然还存在一个问题,就是相机的分辨率和我们的截图分辨率也许是不同的(我在我的三星手机上,我把一个480x320屏幕截图延伸到2560x1920 大小的图片)。一个围绕它的解决方法就是扩大Libgdx视图的尺寸到更大,比实际物理设备的尺寸要大,要实现他需要使用setFixedSize()功能。真实的屏幕尺寸是根据BPU内存。
651 | 然而,在这个时间中我设法去设置虚拟屏幕尺寸为960x640(可能因为GPU显存已经被origin的带下分配了)
652 |
653 |
654 | ```java
655 | public void setFixedSize(int width, int height) {
656 | if (graphics.getView() instanceof SurfaceView) {
657 | SurfaceView glView = (SurfaceView) graphics.getView();
658 | glView.getHolder().setFixedSize(width, height);
659 | glView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
660 | }
661 | }
662 | public void restoreFixedSize() {
663 | if (graphics.getView() instanceof SurfaceView) {
664 | SurfaceView glView = (SurfaceView) graphics.getView();
665 | glView.getHolder().setFixedSize(origWidth, origHeight);
666 | glView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
667 | }
668 | }
669 | ```
670 | **一些小提示**
671 |
672 | 1. 提示1
673 | 注意,代码仅仅适用于Android平台,并非跨平台解决方法,但是我觉得至少在桌面端,应该可以提供类似功能的代码
674 | 2. 提示2
675 | 在整合图片,并将图片数据保存到存储器上时,会花大量的时间,是因为libgdx颜色方案是RGBA而bitmap颜色方案是ARGB
676 | 3. 提示3
677 | 最后需要注意的
678 | 我仅仅测试了一部分Android设备,不同的GPU会产生不同的现象。
679 | **完整代码已上传github**
680 | [https://github.com/54wall/LibgdxAndroidCamera](https://github.com/54wall/LibgdxAndroidCamera)
681 | 最后的截图,按下camera可以开启相机,看下shot,就是进行拍摄,move可以控制猫向右侧移动
682 |
683 | 
684 |
--------------------------------------------------------------------------------