赞
踩
- package com.facepp.xbdemo.util;
-
- import android.opengl.GLES11Ext;
- import android.opengl.GLES20;
- import android.opengl.Matrix;
- import android.util.Log;
-
- import java.nio.ByteBuffer;
- import java.nio.ByteOrder;
- import java.nio.FloatBuffer;
- import java.nio.IntBuffer;
- import java.nio.ShortBuffer;
-
- public class CameraMatrix {
-
- // vertex着色器code
- private final String vertexShaderCode = "attribute vec4 vPosition;"
- + "attribute vec2 inputTextureCoordinate;"
- + "varying vec2 textureCoordinate;" + "void main()" + "{"
- + "gl_Position = vPosition; gl_PointSize = 10.0;"
- + "textureCoordinate = inputTextureCoordinate;" + "}";
-
- // fragment着色器code
- private final String fragmentShaderCode = "#extension GL_OES_EGL_image_external : require\n"
- + "precision mediump float;"
- + "varying vec2 textureCoordinate;\n"
- + "uniform samplerExternalOES s_texture;\n"
- + "void main() {"
- + " gl_FragColor = texture2D( s_texture, textureCoordinate );\n"
- + "}";
-
- private FloatBuffer vertexBuffer, textureVerticesBuffer;
- private ShortBuffer drawListBuffer;
- private final int mProgram;
- private String mtype;
-
- // // private FloatBuffer triangleVB;
- // public ArrayList<ArrayList> points = new ArrayList<ArrayList>();
-
- private short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices
- // (命令绘制顶点)
-
- // number of coordinates per vertex in this array (顶点坐标数)
- private static final int COORDS_PER_VERTEX = 2;
- // 顶点步幅
- private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per
- // vertex
- // 直角坐标系 OLD 用于普通手机相机
- // static float squareCoords[] = {
- // -1.0f, 1.0f,
- // -1.0f, -1.0f,
- // 1.0f, -1.0f,
- // 1.0f, 1.0f, };
-
- // 直角坐标系 OLD左偏转90° 适配执法仪后置摄像头
- // static float squareCoords[] = {
- // -1.0f, -1.0f,
- // 1.0f, -1.0f,
- // 1.0f, 1.0f,
- // -1.0f, 1.0f, };
- private final float squareCoords[];
-
- // 结构顶点(8个数字表示了4个点x,y的位置.大小在0-1之间)
- // static float textureVertices[] = {
- // 1.0f, 1.0f,
- // 1.0f, 0.0f,
- // 0.0f, 0.0f,
- // 0.0f, 1.0f, };
-
- //OLD
- static float textureVertices[] = {
- 0.0f, 1.0f,
- 1.0f, 1.0f,
- 1.0f, 0.0f,
- 0.0f, 0.0f, };
- private int mTextureID;
-
- static float LineCoords[] = { 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f };
-
- private final int VertexCount = LineCoords.length / 3;
-
- public CameraMatrix(int textureID) {
- mtype = OpenGLUtil.getMobileMode();
- Log.e("wyd1","mtype="+mtype);
- if ("Z1".equals(mtype) || "HisenseZ1".equals(mtype) || "Hisense Z1".equals(mtype)) {
- squareCoords = new float[]{
- -1.0f, -1.0f,
- 1.0f, -1.0f,
- 1.0f, 1.0f,
- -1.0f, 1.0f,};
- Log.e("wyd1","mtype执法仪="+mtype);
- }else {
- squareCoords = new float[]{
- -1.0f, 1.0f,
- -1.0f, -1.0f,
- 1.0f, -1.0f,
- 1.0f, 1.0f, };
- Log.e("wyd1","mtype普通手机="+mtype);
- }
-
- this.mTextureID = textureID;
- // initialize vertex byte buffer for shape coordinates(初始化顶点字节缓冲区形状坐标)
- vertexBuffer = floatBufferUtil(squareCoords);
- // initialize byte buffer for the draw list (绘制列表初始化字节缓冲区)
- drawListBuffer = ShortBufferUtil(drawOrder);
- // initialize textureVertices byte buffer for shape
- // coordinates(初始化结构顶点字节缓冲区形状坐标)
- textureVerticesBuffer = floatBufferUtil(textureVertices);
-
- mProgram = GLES20.glCreateProgram(); // create empty OpenGL ES Program
-
- // 拿出两个着色器 顶点着色器和碎片着色器
- int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
- GLES20.glAttachShader(mProgram, vertexShader); // add the vertex shader
-
- int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER,
- fragmentShaderCode);
- GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment
- // shader to program
- GLES20.glLinkProgram(mProgram); // creates OpenGL ES program executables
- }
-
- /**
- * 绘制:
- *
- * 我们在 onDrawFrame 回调中执行绘制操作,绘制的过程其实就是为 shader 代码变量赋值,并调用绘制命令的过程:
- */
- public void draw(float[] mtx) {
- // to program
- GLES20.glUseProgram(mProgram);
-
- GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
- GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mTextureID);
- // get handle to vertex shader's vPosition member
- // (顶点着色器的vPosition成员得到处理)
- int mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
-
- // Enable a handle to the triangle vertices(使一个句柄三角形顶点)
- GLES20.glEnableVertexAttribArray(mPositionHandle);
-
- // Prepare the <insert shape here> coordinate data (准备<插入形状这里>坐标数据)
- GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
- GLES20.GL_FLOAT, false, vertexStride, vertexBuffer);
-
- int mTextureCoordHandle = GLES20.glGetAttribLocation(mProgram,
- "inputTextureCoordinate");
- GLES20.glEnableVertexAttribArray(mTextureCoordHandle);
-
- //照相机镜像
- textureVerticesBuffer.clear();
- textureVerticesBuffer.put(transformTextureCoordinates(textureVertices,
- mtx));
- textureVerticesBuffer.position(0);
-
- GLES20.glVertexAttribPointer(mTextureCoordHandle, COORDS_PER_VERTEX,
- GLES20.GL_FLOAT, false, vertexStride, textureVerticesBuffer);
- GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length,
- GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
-
- // for (int i = 0; i < points.size(); i++) {
- // ArrayList<FloatBuffer> triangleVBList = points.get(i);
- // for (int j = 0; j < triangleVBList.size(); j++) {
- // FloatBuffer fb = triangleVBList.get(j);
- // GLES20.glVertexAttribPointer(mPositionHandle, 3,
- // GLES20.GL_FLOAT, false, 0, fb);
- // GLES20.glEnableVertexAttribArray(mPositionHandle);
- // // Draw the point
- // GLES20.glDrawArrays(GLES20.GL_POINTS, 0, 1);
- // }
- // }
-
- // Disable vertex array
- GLES20.glDisableVertexAttribArray(mPositionHandle);
- GLES20.glDisableVertexAttribArray(mTextureCoordHandle);
- }
-
- public boolean isDraw = false;
-
- /**
- * 图像旋转
- */
- private float[] transformTextureCoordinates(float[] coords, float[] matrix) {
- float[] result = new float[coords.length];
- float[] vt = new float[4];
-
- for (int i = 0; i < coords.length; i += 2) {
- float[] v = { coords[i], coords[i + 1], 0, 1 };
- // for (int j = 0; j < v.length; j ++) {
- // Log.w("ceshi", "v[" + j + "]======" + coords[j]);
- // }
- Matrix.multiplyMV(vt, 0, matrix, 0, v, 0);
- result[i] = vt[0];// x轴镜像
- // result[i + 1] = vt[1];y轴镜像
- result[i + 1] = coords[i + 1];
- }
- //
- // for (int i = 0; i < coords.length; i ++) {
- // Log.w("ceshi", "coords[" + i + "]======" + coords[i]);
- // }
- //
- // for (int i = 0; i < result.length / 2; i ++) {
- // Log.w("ceshi", "result[" + i + "]======" + result[i]);
- // }
-
- // [0.0, 1.0, 1.0, 1.0]; v
- // [0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0]; coords
- // [1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0]; result
-
- return result;
- }
-
- /**
- * 加载 著色器
- */
- private int loadShader(int type, String shaderCode) {
- // create a vertex shader type (GLES20.GL_VERTEX_SHADER)
- // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
- int shader = GLES20.glCreateShader(type);
-
- // add the source code to the shader and compile it
- GLES20.glShaderSource(shader, shaderCode);
- GLES20.glCompileShader(shader);
-
- return shader;
- }
-
- // 定义一个工具方法,将int[]数组转换为OpenGL ES所需的IntBuffer
- private IntBuffer intBufferUtil(int[] arr) {
- // 初始化ByteBuffer,长度为arr数组的长度*4,因为一个int占4个字节
- ByteBuffer qbb = ByteBuffer.allocateDirect(arr.length * 4);
- // 数组排列用nativeOrder
- qbb.order(ByteOrder.nativeOrder());
- IntBuffer mBuffer = qbb.asIntBuffer();
- mBuffer.put(arr);
- mBuffer.position(0);
- return mBuffer;
- }
-
- // 定义一个工具方法,将float[]数组转换为OpenGL ES所需的FloatBuffer
- public FloatBuffer floatBufferUtil(float[] arr) {
- // 初始化ByteBuffer,长度为arr数组的长度*4,因为一个int占4个字节
- ByteBuffer qbb = ByteBuffer.allocateDirect(arr.length * 4);
- // 数组排列用nativeOrder
- qbb.order(ByteOrder.nativeOrder());
- FloatBuffer mBuffer = qbb.asFloatBuffer();
- mBuffer.put(arr);
- mBuffer.position(0);
- return mBuffer;
- }
-
- // 定义一个工具方法,将Short[]数组转换为OpenGL ES所需的ShortBuffer
- private ShortBuffer ShortBufferUtil(short[] arr) {
- ByteBuffer dlb = ByteBuffer.allocateDirect(arr.length * 2);
- dlb.order(ByteOrder.nativeOrder());
- ShortBuffer buffer = dlb.asShortBuffer();
- buffer.put(arr);
- buffer.position(0);
-
- return buffer;
- }
-
- // 定义一个工具方法,将Short[]数组转换为OpenGL ES所需的ShortBuffer
- private ByteBuffer ByteBufferUtil(Byte[] arr) {
- ByteBuffer dlb = ByteBuffer.allocateDirect(arr.length);
- // dlb.order(ByteOrder.nativeOrder());
- // ByteBuffer buffer = dlb.asShortBuffer();
- // buffer.put(arr);
- dlb.position(0);
-
- return dlb;
- }
- }

package com.facepp.xbdemo.util;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.graphics.YuvImage;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.util.Log;
import android.view.Surface;
import android.widget.RelativeLayout;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
/**
* 照相机工具类
*/
public class ICamera {
private String mtype;
public Camera mCamera;
public int cameraWidth;
public int cameraHeight;
public int cameraId = 1;// 前置摄像头
public int Angle;
public ICamera() {
mtype = OpenGLUtil.getMobileMode();
}
/**
* 打开相机
*/
public Camera openCamera(boolean isBackCamera, Activity activity, HashMap<String, Integer> resolutionMap) {
try {
if (isBackCamera)
cameraId = 0;
else
cameraId = 1;
int width = 640;
int height = 480;
if (resolutionMap != null) {
width = resolutionMap.get("width");
height = resolutionMap.get("height");
}
mCamera = Camera.open(cameraId);
CameraInfo cameraInfo = new CameraInfo();
Camera.getCameraInfo(cameraId, cameraInfo);
Camera.Parameters params = mCamera.getParameters();
// Camera.Size bestPreviewSize = calBestPreviewSize(
// mCamera.getParameters(), Screen.mWidth, Screen.mHeight);
Camera.Size bestPreviewSize = calBestPreviewSize(
mCamera.getParameters(), width, height);
cameraWidth = bestPreviewSize.width;
cameraHeight = bestPreviewSize.height;
params.setPreviewSize(cameraWidth, cameraHeight);
Angle = getCameraAngle(activity);
Log.w("ceshi", "Angle==" + Angle);
Log.d("ceshi", "width = " + cameraWidth + ", height = " + cameraHeight);
// mCamera.setDisplayOrientation(Angle);
mCamera.setParameters(params);
return mCamera;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public boolean isBackCamera(){
return cameraId==1?false:true;
}
// 通过屏幕参数、相机预览尺寸计算布局参数
public RelativeLayout.LayoutParams getLayoutParam() {
float scale = cameraWidth * 1.0f / cameraHeight;
int layout_width = Screen.mWidth;
int layout_height = (int) (layout_width * scale);
if (Screen.mWidth >= Screen.mHeight) {
layout_height = Screen.mHeight;
layout_width = (int) (layout_height / scale);
}
RelativeLayout.LayoutParams layout_params = new RelativeLayout.LayoutParams(
layout_width, layout_height);
layout_params.addRule(RelativeLayout.CENTER_HORIZONTAL);// 设置照相机水平居中
return layout_params;
}
/**
* 开始检测脸
*/
public void actionDetect(Camera.PreviewCallback mActivity) {
if (mCamera != null) {
mCamera.setPreviewCallback(mActivity);
}
}
public void startPreview(SurfaceTexture surfaceTexture) {
if (mCamera != null) {
try {
mCamera.setPreviewTexture(surfaceTexture);
mCamera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void closeCamera() {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.setPreviewCallback(null);
mCamera.release();
mCamera = null;
}
}
public static ArrayList<HashMap<String, Integer>> getCameraPreviewSize(
int cameraId) {
ArrayList<HashMap<String, Integer>> size = new ArrayList<HashMap<String, Integer>>();
Camera camera = null;
try {
camera = Camera.open(cameraId);
if (camera == null)
camera = Camera.open(0);
List<Camera.Size> allSupportedSize = camera.getParameters()
.getSupportedPreviewSizes();
for (Camera.Size tmpSize : allSupportedSize) {
if (tmpSize.width > tmpSize.height) {
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("width", tmpSize.width);
map.put("height", tmpSize.height);
if (tmpSize.width==640&&tmpSize.height==480){
size.add(map);
}
if (tmpSize.width==960&&tmpSize.height==540){
size.add(map);
}
if (tmpSize.width==1280&&tmpSize.height==720){
size.add(map);
}
if (tmpSize.width==1920&&tmpSize.height==1080){
size.add(map);
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (camera != null) {
camera.stopPreview();
camera.setPreviewCallback(null);
camera.release();
camera = null;
}
}
return size;
}
/**
* 通过传入的宽高算出最接近于宽高值的相机大小
*/
private Camera.Size calBestPreviewSize(Camera.Parameters camPara,
final int width, final int height) {
List<Camera.Size> allSupportedSize = camPara.getSupportedPreviewSizes();
ArrayList<Camera.Size> widthLargerSize = new ArrayList<Camera.Size>();
for (Camera.Size tmpSize : allSupportedSize) {
Log.w("ceshi", "tmpSize.width===" + tmpSize.width
+ ", tmpSize.height===" + tmpSize.height);
if (tmpSize.width > tmpSize.height) {
widthLargerSize.add(tmpSize);
}
}
Collections.sort(widthLargerSize, new Comparator<Camera.Size>() {
@Override
public int compare(Camera.Size lhs, Camera.Size rhs) {
int off_one = Math.abs(lhs.width * lhs.height - width * height);
int off_two = Math.abs(rhs.width * rhs.height - width * height);
return off_one - off_two;
}
});
return widthLargerSize.get(0);
}
/**
* 打开前置或后置摄像头
*/
public Camera getCameraSafely(int cameraId) {
Camera camera = null;
try {
camera = Camera.open(cameraId);
} catch (Exception e) {
camera = null;
}
return camera;
}
public Bitmap getBitMap(byte[] data, boolean mIsFrontalCamera){
return getBitMap(data, mCamera, mIsFrontalCamera);
}
public Bitmap getBitMap(byte[] data, Camera camera, boolean mIsFrontalCamera) {
int width = camera.getParameters().getPreviewSize().width;
int height = camera.getParameters().getPreviewSize().height;
YuvImage yuvImage = new YuvImage(data, camera.getParameters()
.getPreviewFormat(), width, height, null);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
yuvImage.compressToJpeg(new Rect(0, 0, width, height), 80,
byteArrayOutputStream);
byte[] jpegData = byteArrayOutputStream.toByteArray();
// 获取照相后的bitmap
Bitmap tmpBitmap = BitmapFactory.decodeByteArray(jpegData, 0,
jpegData.length);
///将图片流方向转换
Matrix matrix = new Matrix();
matrix.reset();
if (mIsFrontalCamera) {
matrix.setRotate(-90);
} else {
// matrix.setRotate(90);//用于普通手机后置摄像头
// matrix.setRotate(0);//用于执法仪后置摄像头
Log.e("wyd1","mtype转换图片方向="+mtype);
if ("Z1".equals(mtype) || "HisenseZ1".equals(mtype) || "Hisense Z1".equals(mtype)) {
matrix.setRotate(0);//用于执法仪后置摄像头
}else {
matrix.setRotate(90);//用于普通手机后置摄像头
}
}
///将图片流方向转换
tmpBitmap = Bitmap.createBitmap(tmpBitmap, 0, 0, tmpBitmap.getWidth(),
tmpBitmap.getHeight(), matrix, true);
tmpBitmap = tmpBitmap.copy(Bitmap.Config.ARGB_8888, true);
int hight = tmpBitmap.getHeight() > tmpBitmap.getWidth() ? tmpBitmap
.getHeight() : tmpBitmap.getWidth();
float scale = hight / 800.0f;
if (scale > 1) {
tmpBitmap = Bitmap.createScaledBitmap(tmpBitmap,
(int) (tmpBitmap.getWidth() / scale),
(int) (tmpBitmap.getHeight() / scale), false);
}
return tmpBitmap;
}
public Bitmap getBitMapWithRect(byte[] data, Camera camera, boolean mIsFrontalCamera,Rect rect) {
int width = camera.getParameters().getPreviewSize().width;
int height = camera.getParameters().getPreviewSize().height;
YuvImage yuvImage = new YuvImage(data, camera.getParameters()
.getPreviewFormat(), width, height, null);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
yuvImage.compressToJpeg(new Rect(0, 0, width, height), 80,
byteArrayOutputStream);
byte[] jpegData = byteArrayOutputStream.toByteArray();
// 获取照相后的bitmap
Bitmap tmpBitmap = BitmapFactory.decodeByteArray(jpegData, 0,
jpegData.length);
// Log.e("xie", "getbitmap width"+tmpBitmap.getWidth()+"rect="+rect );
if (rect.top<0){
rect.top=0;
}
if (rect.top>tmpBitmap.getHeight()){
rect.top=tmpBitmap.getHeight();
}
if (rect.left<0){
rect.left=0;
}
if (rect.left>tmpBitmap.getWidth()){
rect.left=tmpBitmap.getWidth();
}
int widthRect=rect.right-rect.left;
if(rect.right>tmpBitmap.getWidth()){
widthRect=tmpBitmap.getWidth()-rect.left;
}
int heightRect=rect.bottom-rect.top;
if(rect.bottom>tmpBitmap.getHeight()){
heightRect=tmpBitmap.getHeight()-rect.top;
}
// Log.i("xie","xie rect"+rect+"wid"+widthRect+"height"+heightRect);
tmpBitmap = Bitmap.createBitmap(tmpBitmap, rect.left, rect.top, widthRect,
heightRect);
Matrix matrix = new Matrix();
matrix.reset();
if (mIsFrontalCamera) {
matrix.setRotate(-90);
} else {
matrix.setRotate(90);
}
tmpBitmap = Bitmap.createBitmap(tmpBitmap, 0, 0, tmpBitmap.getWidth(),
tmpBitmap.getHeight(), matrix, true);
// Log.e("xie", "getbitmap temp"+tmpBitmap.getWidth()+"asdhe "+tmpBitmap.getHeight() );
tmpBitmap = tmpBitmap.copy(Bitmap.Config.ARGB_8888, true);
int hight = tmpBitmap.getHeight() > tmpBitmap.getWidth() ? tmpBitmap
.getHeight() : tmpBitmap.getWidth();
float scale = hight / 800.0f;
if (scale > 1) {
tmpBitmap = Bitmap.createScaledBitmap(tmpBitmap,
(int) (tmpBitmap.getWidth() / scale),
(int) (tmpBitmap.getHeight() / scale), false);
}
return tmpBitmap;
}
/**
* 获取照相机旋转角度
*/
public int getCameraAngle(Activity activity) {
int rotateAngle = 90;
CameraInfo info = new CameraInfo();
Camera.getCameraInfo(cameraId, info);
int rotation = activity.getWindowManager().getDefaultDisplay()
.getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0:
degrees = 0;
break;
case Surface.ROTATION_90:
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}
if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
rotateAngle = (info.orientation + degrees) % 360;
rotateAngle = (360 - rotateAngle) % 360; // compensate the mirror
} else { // back-facing
rotateAngle = (info.orientation - degrees + 360) % 360;
}
return rotateAngle;
}
}
//
package com.facepp.xbdemo;
import android.app.Activity;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.PreviewCallback;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.GLSurfaceView.Renderer;
import android.opengl.Matrix;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Vibrator;
import android.util.Base64;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.facepp.xbdemo.bean.FaceActionInfo;
import com.facepp.xbdemo.bean.FeatureInfo;
import com.facepp.xbdemo.facecompare.FaceCompareManager;
import com.facepp.xbdemo.mediacodec.MediaHelper;
import com.facepp.xbdemo.util.CameraMatrix;
import com.facepp.xbdemo.util.ConUtil;
import com.facepp.xbdemo.util.DialogUtil;
import com.facepp.xbdemo.util.ICamera;
import com.facepp.xbdemo.util.MediaRecorderUtil;
import com.facepp.xbdemo.util.OpenGLDrawRect;
import com.facepp.xbdemo.util.OpenGLUtil;
import com.facepp.xbdemo.util.PointsMatrix;
import com.facepp.xbdemo.util.Screen;
import com.facepp.xbdemo.util.SensorEventUtil;
import com.megvii.facepp.sdk.Facepp;
import java.io.ByteArrayOutputStream;
import java.net.URLEncoder;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.logging.Logger;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
public class OpenglActivity extends Activity
implements PreviewCallback, Renderer, SurfaceTexture.OnFrameAvailableListener {
private boolean isStartRecorder, is3DPose, isDebug, isROIDetect, is106Points, isBackCamera, isFaceProperty,
isOneFaceTrackig, isFaceCompare, isShowFaceRect;
private String trackModel;
private int printTime = 31;
private GLSurfaceView mGlSurfaceView;
private ICamera mICamera;
private Camera mCamera;
private DialogUtil mDialogUtil;
private TextView debugInfoText, debugPrinttext, AttriButetext;
private TextView featureTargetText;
private ImageButton btnAddFeature;
private HandlerThread mHandlerThread = new HandlerThread("facepp");
private Handler mHandler;
private Facepp facepp;
private MediaRecorderUtil mediaRecorderUtil;
private int min_face_size = 200;
private int detection_interval = 25;
private HashMap<String, Integer> resolutionMap;
private SensorEventUtil sensorUtil;
private float roi_ratio = 0.8f;
private byte[] newestFeature;
private byte[] carmeraImgData;
private int screenWidth;
private int screenHeight;
private boolean isSurfaceCreated;
private FaceActionInfo faceActionInfo;
private ImageView imgIcon;
private MediaHelper mMediaHelper;
//创建震动服务对象
private Vibrator mVibrator;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Screen.initialize(this);
setContentView(R.layout.activity_opengl);
init();
// new Handler().postDelayed(new Runnable() {
// @Override
// public void run() {
// startRecorder();
// }
// }, 2000);
FaceCompareManager.instance().loadFeature(this);
// ConUtil.toggleHideyBar(this);
DisplayMetrics outMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(outMetrics);
screenWidth = outMetrics.widthPixels;
screenHeight = outMetrics.heightPixels;
}
private void init() {
//获取手机震动服务
mVibrator=(Vibrator)getApplication().getSystemService(Service.VIBRATOR_SERVICE);
if (android.os.Build.MODEL.equals("PLK-AL10"))
printTime = 50;
faceActionInfo = (FaceActionInfo) getIntent().getSerializableExtra("FaceAction");
isStartRecorder = faceActionInfo.isStartRecorder;
is3DPose = faceActionInfo.is3DPose;
isDebug = faceActionInfo.isdebug;
isROIDetect = faceActionInfo.isROIDetect;
is106Points = faceActionInfo.is106Points;
isBackCamera = faceActionInfo.isBackCamera;
isFaceProperty = faceActionInfo.isFaceProperty;
isOneFaceTrackig = faceActionInfo.isOneFaceTrackig;
isFaceCompare = faceActionInfo.isFaceCompare;
trackModel = faceActionInfo.trackModel;
min_face_size = faceActionInfo.faceSize;
detection_interval = faceActionInfo.interval;
resolutionMap = faceActionInfo.resolutionMap;
//初始化实例
facepp = new Facepp();
sensorUtil = new SensorEventUtil(this);
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper());
mGlSurfaceView = (GLSurfaceView) findViewById(R.id.opengl_layout_surfaceview);
mGlSurfaceView.setEGLContextClientVersion(2);// 创建一个OpenGL ES 2.0
// context
mGlSurfaceView.setRenderer(this);// 设置渲染器进入gl
// RENDERMODE_CONTINUOUSLY不停渲染
// RENDERMODE_WHEN_DIRTY懒惰渲染,需要手动调用 glSurfaceView.requestRender() 才会进行更新
mGlSurfaceView.setRenderMode(mGlSurfaceView.RENDERMODE_WHEN_DIRTY);// 设置渲染器模式
mGlSurfaceView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
autoFocus();
Toast.makeText(OpenglActivity.this, "聚焦相机", Toast.LENGTH_SHORT).show();
}
});
mICamera = new ICamera();
mDialogUtil = new DialogUtil(this);
debugInfoText = (TextView) findViewById(R.id.opengl_layout_debugInfotext);
AttriButetext = (TextView) findViewById(R.id.opengl_layout_AttriButetext);
debugPrinttext = (TextView) findViewById(R.id.opengl_layout_debugPrinttext);
if (isDebug)
debugInfoText.setVisibility(View.VISIBLE);
else
debugInfoText.setVisibility(View.INVISIBLE);
btnAddFeature = (ImageButton) findViewById(R.id.opengl_layout_addFaceInfo);
btnAddFeature.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// 保存feature数据
if (mICamera==null||mICamera.mCamera==null){
return;
}
if (compareFaces == null || compareFaces.length <= 0 || carmeraImgData == null) {
Toast.makeText(OpenglActivity.this, "当前未检测到人脸", Toast.LENGTH_SHORT).show();
return;
}
Log.e("xie","xie rect"+compareFaces[0].rect.top+"bottom"+compareFaces[0].rect.bottom+newestFeature);
FaceCompareManager.instance().startActivity(OpenglActivity.this, compareFaces, mICamera, carmeraImgData, isBackCamera, faceActionInfo);
}
});
featureTargetText = (TextView) findViewById(R.id.opengl_layout_targetFaceName);
if (isFaceCompare) {
btnAddFeature.setVisibility(View.VISIBLE);
} else {
btnAddFeature.setVisibility(View.GONE);
// btnAddFeature.setVisibility(View.VISIBLE);
}
imgIcon = (ImageView) findViewById(R.id.opengl_layout_icon);
}
/**
* 开始录制
*/
private void startRecorder() {
if (isStartRecorder) {
int Angle = 360 - mICamera.Angle;
if (isBackCamera)
Angle = mICamera.Angle;
mediaRecorderUtil = new MediaRecorderUtil(this, mCamera, mICamera.cameraWidth, mICamera.cameraHeight);
isStartRecorder = mediaRecorderUtil.prepareVideoRecorder(Angle);
if (isStartRecorder) {
boolean isRecordSucess = mediaRecorderUtil.start();
if (isRecordSucess)
mICamera.actionDetect(this);
else
mDialogUtil.showDialog(getResources().getString(R.string.no_record));
}
}
}
private void autoFocus() {
if (mCamera != null && isBackCamera) {
mCamera.cancelAutoFocus();
Parameters parameters = mCamera.getParameters();
parameters.setFocusMode(Parameters.FOCUS_MODE_AUTO);
mCamera.setParameters(parameters);
mCamera.autoFocus(null);
}
}
private int Angle;
@Override
protected void onResume() {
super.onResume();
ConUtil.acquireWakeLock(this);
startTime = System.currentTimeMillis();
mCamera = mICamera.openCamera(isBackCamera, this, resolutionMap);
if (mCamera != null) {
Angle = 360 - mICamera.Angle;
if (isBackCamera)
Angle = mICamera.Angle;
RelativeLayout.LayoutParams layout_params = mICamera.getLayoutParam();
mGlSurfaceView.setLayoutParams(layout_params);
int width = mICamera.cameraWidth;
int height = mICamera.cameraHeight;
int left = 0;
int top = 0;
int right = width;
int bottom = height;
if (isROIDetect) {
float line = height * roi_ratio;
left = (int) ((width - line) / 2.0f);
top = (int) ((height - line) / 2.0f);
right = width - left;
bottom = height - top;
}
//初始化模型,如果模型加载失败,会有相应的code提示
String errorCode = facepp.init(this, ConUtil.getFileContent(this, R.raw.megviifacepp_0_5_2_model), isOneFaceTrackig ? 1 : 0);
//sdk内部其他api已经处理好,可以不判断
if (errorCode!=null){
Intent intent=new Intent();
intent.putExtra("errorcode",errorCode);
setResult(101,intent);
finish();
return;
}
//2. 检测参数设置
//主要根据需要的模型的能力去设置detectionMode,其他的参数使用默认即可
Facepp.FaceppConfig faceppConfig = facepp.getFaceppConfig();
faceppConfig.interval = detection_interval;
faceppConfig.minFaceSize = min_face_size;
faceppConfig.roi_left = left;
faceppConfig.roi_top = top;
faceppConfig.roi_right = right;
faceppConfig.roi_bottom = bottom;
String[] array = getResources().getStringArray(R.array.trackig_mode_array);
if (trackModel.equals(array[0]))
faceppConfig.detectionMode = Facepp.FaceppConfig.DETECTION_MODE_TRACKING_FAST;
else if (trackModel.equals(array[1]))
faceppConfig.detectionMode = Facepp.FaceppConfig.DETECTION_MODE_TRACKING_ROBUST;
else if (trackModel.equals(array[2])) {
faceppConfig.detectionMode = Facepp.FaceppConfig.MG_FPP_DETECTIONMODE_TRACK_RECT;
isShowFaceRect = true;
}
facepp.setFaceppConfig(faceppConfig);
String version = facepp.getVersion();
Log.d("ceshi", "onResume:version:" + version);
} else {
mDialogUtil.showDialog(getResources().getString(R.string.camera_error));
}
mMediaHelper = new MediaHelper(mICamera.cameraWidth, mICamera.cameraHeight, true, mGlSurfaceView);
// newMethodCall();
}
private void setConfig(int rotation) {
Facepp.FaceppConfig faceppConfig = facepp.getFaceppConfig();
if (faceppConfig.rotation != rotation) {
faceppConfig.rotation = rotation;
facepp.setFaceppConfig(faceppConfig);
}
}
/**
* 画绿色框
*/
private void drawShowRect() {
mPointsMatrix.vertexBuffers = OpenGLDrawRect.drawCenterShowRect(isBackCamera, mICamera.cameraWidth,
mICamera.cameraHeight, roi_ratio);
}
boolean isSuccess = false;
float confidence;
float pitch, yaw, roll;
long startTime;
long time_AgeGender_end = 0;
String AttriButeStr = "";
int rotation = Angle;
int preRotation = rotation;
Facepp.Face[] compareFaces;
long detectGenderAgeTime;
final int DETECT_GENDER_INTERVAL = 1000;
long featureTime = 0;
private ArrayList<TextView> tvFeatures = new ArrayList<>();
long matrixTime;
private int prefaceCount = 0;
private boolean isFirst = true;
@Override
public void onPreviewFrame(final byte[] imgData, final Camera camera) {
Log.e("wyd","onPreviewFrame1>>"+Angle);
//检测操作放到主线程,防止贴点延迟
int width = mICamera.cameraWidth;
int height = mICamera.cameraHeight;
long faceDetectTime_action = System.currentTimeMillis();
final int orientation = sensorUtil.orientation;
if (orientation == 0)
rotation = Angle;
else if (orientation == 1)
rotation = 0;
else if (orientation == 2)
rotation = 180;
else if (orientation == 3)
rotation = 360 - Angle;
Log.e("wyd","onPreviewFrame>>"+Angle+"orientation="+orientation+"rotation="+rotation);
setConfig(rotation);
//这里会获取检测到人脸的数目,和人脸框置信度等基本信息。参数为检测图片的属性,imageMode目前支持两种bgr nv21
final Facepp.Face[] faces = facepp.detect(imgData, width, height, Facepp.IMAGEMODE_NV21);
final long algorithmTime = System.currentTimeMillis() - faceDetectTime_action;
if (faces != null) {
long actionMaticsTime = System.currentTimeMillis();
ArrayList<ArrayList> pointsOpengl = new ArrayList<ArrayList>();
ArrayList<FloatBuffer> rectsOpengl = new ArrayList<FloatBuffer>();
if (faces.length > 0) {
for (int c = 0; c < faces.length; c++) {
if (is106Points) {
//获取人脸的关键点,tracking检测的会做平滑,参数pointNum有81点和106点
facepp.getLandmarkRaw(faces[c], Facepp.FPP_GET_LANDMARK106);
if (isFirst) {
isFirst = false;
//设置震动周期,数组表示时间:等待+执行,单位是毫秒,下面操作代表:等待100,执行100,等待100,执行1000,
//后面的数字如果为-1代表不重复,之执行一次,其他代表会重复,0代表从数组的第0个位置开始
mVibrator.vibrate(new long[]{100,100,100,1000},-1);
Toast.makeText(OpenglActivity.this, "检测到人脸关键点", Toast.LENGTH_SHORT).show();
//生成图片 转成流
Bitmap bitmap = mICamera.getBitMap(imgData,!isBackCamera);
Log.e("wyd",bitmap.getWidth()+""+bitmap.getByteCount());
String imgStr = Bitmap2BASE64(bitmap);
Log.e("wyd","imgStr="+imgStr);
imgIcon.setImageBitmap(bitmap);
}
}else {
facepp.getLandmarkRaw(faces[c], Facepp.FPP_GET_LANDMARK81);
if (isFirst) {
isFirst = false;
//设置震动周期,数组表示时间:等待+执行,单位是毫秒,下面操作代表:等待100,执行100,等待100,执行1000,
//后面的数字如果为-1代表不重复,之执行一次,其他代表会重复,0代表从数组的第0个位置开始
mVibrator.vibrate(new long[]{100,100,100,1000},-1);
Toast.makeText(OpenglActivity.this, "检测到人脸关键点", Toast.LENGTH_SHORT).show();
//生成图片 转成流
Bitmap bitmap = mICamera.getBitMap(imgData,!isBackCamera);
Log.e("wyd",bitmap.getWidth()+""+bitmap.getByteCount());
String imgStr = Bitmap2BASE64(bitmap);
Log.e("wyd","imgStr="+imgStr);
imgIcon.setImageBitmap(bitmap);
}
}
if (is3DPose) {
facepp.get3DPose(faces[c]);
}
final Facepp.Face face = faces[c];
pitch = faces[c].pitch;
yaw = faces[c].yaw;
roll = faces[c].roll;
confidence = faces[c].confidence;
//显示人脸点///
//0.4.7之前(包括)jni把所有角度的点算到竖直的坐标,所以外面画点需要再调整回来,才能与其他角度适配
//目前getLandmarkOrigin会获得原始的坐标,所以只需要横屏适配好其他的角度就不用适配了,因为texture和preview的角度关系是固定的
// ArrayList<FloatBuffer> triangleVBList = new ArrayList<FloatBuffer>();
// for (int i = 0; i < faces[c].points.length; i++) {
// float x = (faces[c].points[i].x / width) * 2 - 1;
// if (isBackCamera)
// x = -x;
// float y = (faces[c].points[i].y / height) * 2-1;
// float[] pointf = new float[]{y, x, 0.0f};
// FloatBuffer fb = mCameraMatrix.floatBufferUtil(pointf);
// triangleVBList.add(fb);
// }
//
//
// pointsOpengl.add(triangleVBList);
// if (mPointsMatrix.isShowFaceRect) {
// facepp.getRect(faces[c]);
// FloatBuffer buffer = calRectPostion(faces[c].rect, mICamera.cameraWidth, mICamera.cameraHeight);
// rectsOpengl.add(buffer);
// }
}
} else {
isFirst = true;
//取消震动
mVibrator.cancel();
pitch = 0.0f;
yaw = 0.0f;
roll = 0.0f;
}
synchronized (mPointsMatrix) {
if (faces.length > 0 && is3DPose)
mPointsMatrix.bottomVertexBuffer = OpenGLDrawRect.drawBottomShowRect(0.15f, 0, -0.7f, pitch,
-yaw, roll, rotation);
else
mPointsMatrix.bottomVertexBuffer = null;
mPointsMatrix.points = pointsOpengl;
mPointsMatrix.faceRects = rectsOpengl;
}
matrixTime = System.currentTimeMillis() - actionMaticsTime;
}
/*if (isSuccess)
return;
isSuccess = true;
mHandler.post(new Runnable() {
@Override
public void run() {
if (faces != null) {
confidence = 0.0f;
if (faces.length > 0) {
//compare ui
runOnUiThread(new Runnable() {
@Override
public void run() {
if (tvFeatures.size() < faces.length) {
int tvFeaturesSize = tvFeatures.size();
for (int i = 0; i < faces.length - tvFeaturesSize; i++) {
TextView textView = new TextView(OpenglActivity.this);
textView.setTextColor(0xff1a1d20);
tvFeatures.add(textView);
}
}
for (int i = prefaceCount; i < faces.length; i++) {
((RelativeLayout) mGlSurfaceView.getParent()).addView(tvFeatures.get(i));
}
for (int i = faces.length; i < tvFeatures.size(); i++) {
((RelativeLayout) mGlSurfaceView.getParent()).removeView(tvFeatures.get(i));
}
prefaceCount = faces.length;
}
});
for (int c = 0; c < faces.length; c++) {
final Facepp.Face face = faces[c];
if (isFaceProperty) {
long time_AgeGender_action = System.currentTimeMillis();
facepp.getAgeGender(faces[c]);
time_AgeGender_end = System.currentTimeMillis() - time_AgeGender_action;
String gender = "man";
if (face.female > face.male)
gender = "woman";
AttriButeStr = "\nage: " + (int) Math.max(face.age, 1) + "\ngender: " + gender;
}
// 添加人脸比对
if (isFaceCompare) {
if (c == 0) {
featureTime = System.currentTimeMillis();
}
if (facepp.getExtractFeature(face)) {
synchronized (OpenglActivity.this) {
newestFeature = face.feature;
carmeraImgData = imgData;
}
if (c == faces.length - 1) {
compareFaces = faces;
}
final FeatureInfo featureInfo = FaceCompareManager.instance().compare(facepp, face.feature);
final int index = c;
runOnUiThread(new Runnable() {
@Override
public void run() {
featureTargetText = tvFeatures.get(index);
if (featureInfo != null) {
featureTargetText.setVisibility(View.VISIBLE);
featureTargetText.setText(featureInfo.title);
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) featureTargetText.getLayoutParams();
int txtWidth = featureTargetText.getWidth();
int txtHeight = featureTargetText.getHeight();
PointF noseP = null;
PointF eyebrowP = null;
if (is106Points){
noseP=face.points[46];
eyebrowP=face.points[37];
}else{
noseP=face.points[34];
eyebrowP=face.points[19];
}
boolean isVertical;
if (orientation==0||orientation==3){
isVertical=true;
}else{
isVertical=false;
}
int tops= (int) (((mICamera.cameraWidth-(isVertical?eyebrowP.x:noseP.x)))*(mGlSurfaceView.getHeight()*1.0f/mICamera.cameraWidth));
int lefts= (int) ((mICamera.cameraHeight-(isVertical?noseP.y:eyebrowP.y))*(mGlSurfaceView.getWidth()*1.0f/mICamera.cameraHeight));
if (isBackCamera){
tops=mGlSurfaceView.getHeight()-tops;
}
tops=tops-txtHeight/2;
lefts=lefts-txtWidth/2;
params.leftMargin = lefts;
params.topMargin = tops;
featureTargetText.setLayoutParams(params);
} else {
featureTargetText.setVisibility(View.INVISIBLE);
}
}
});
}
if (c == faces.length - 1) {
featureTime = System.currentTimeMillis() - featureTime;
}
}
}
} else {
runOnUiThread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < tvFeatures.size(); i++) {
((RelativeLayout) mGlSurfaceView.getParent()).removeView(tvFeatures.get(i));
}
prefaceCount=0;
}
});
mPointsMatrix.rect = null;
compareFaces = null;
}
runOnUiThread(new Runnable() {
@Override
public void run() {
String logStr = "\ncameraWidth: " + mICamera.cameraWidth + "\ncameraHeight: "
+ mICamera.cameraHeight + "\nalgorithmTime: " + algorithmTime + "ms"
+ "\nmatrixTime: " + matrixTime + "\nconfidence:" + confidence;
debugInfoText.setText(logStr);
if (faces.length > 0 && isFaceProperty && AttriButeStr != null && AttriButeStr.length() > 0)
AttriButetext.setText(AttriButeStr + "\nAgeGenderTime:" + time_AgeGender_end);
else
AttriButetext.setText("");
}
});
} else {
compareFaces = null;
}
isSuccess = false;
}
});*/
}
@Override
protected void onPause() {
super.onPause();
ConUtil.releaseWakeLock();
if (mediaRecorderUtil != null) {
mediaRecorderUtil.releaseMediaRecorder();
}
mICamera.closeCamera();
mCamera = null;
Log.e("wyd","onPause>>");
finish();
}
@Override
protected void onDestroy() {
if (mMediaHelper!=null)
mMediaHelper.stopRecording();
super.onDestroy();
mHandler.post(new Runnable() {
@Override
public void run() {
facepp.release();
}
});
Log.e("wyd","onDestroy>>");
}
private int mTextureID = -1;
private SurfaceTexture mSurface;
private CameraMatrix mCameraMatrix;
private PointsMatrix mPointsMatrix;
@Override
public void onFrameAvailable(SurfaceTexture surfaceTexture) {
// TODO Auto-generated method stub
// Log.d("ceshi", "onFrameAvailable");
mGlSurfaceView.requestRender();
Log.e("wyd","onFrameAvailable>>");
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// 黑色背景
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
surfaceInit();
runOnUiThread(new Runnable() {
@Override
public void run() {
int rotation = OpenglActivity.this.getWindowManager().getDefaultDisplay()
.getRotation();
Toast.makeText(OpenglActivity.this, ""+rotation , Toast.LENGTH_SHORT).show();
}
});
Log.e("wyd","onSurfaceCreated>>");
}
private void surfaceInit() {
mTextureID = OpenGLUtil.createTextureID();
mSurface = new SurfaceTexture(mTextureID);
if (isStartRecorder) {
mMediaHelper.startRecording(mTextureID);
}
// 这个接口就干了这么一件事,当有数据上来后会进到onFrameAvailable方法
mSurface.setOnFrameAvailableListener(this);// 设置照相机有数据时进入
mCameraMatrix = new CameraMatrix(mTextureID);
mPointsMatrix = new PointsMatrix(isFaceCompare);
mPointsMatrix.isShowFaceRect = isShowFaceRect;
mICamera.startPreview(mSurface);// 设置预览容器
mICamera.actionDetect(this);
if (isROIDetect)
drawShowRect();
}
private boolean flip = true;
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
Log.e("wyd","onSurfaceChanged>>");
// 设置画面的大小
GLES20.glViewport(0, 0, width, height);
float ratio = (float) width / height;
ratio = 1; // 这样OpenGL就可以按照屏幕框来画了,不是一个正方形了
// this projection matrix is applied to object coordinates
// in the onDrawFrame() method
Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
// Matrix.perspectiveM(mProjMatrix, 0, 0.382f, ratio, 3, 700);
}
private final float[] mMVPMatrix = new float[16];
private final float[] mProjMatrix = new float[16];
private final float[] mVMatrix = new float[16];
private final float[] mRotationMatrix = new float[16];
@Override
public void onDrawFrame(GL10 gl) {
Log.e("wyd","onDrawFrame>>");
final long actionTime = System.currentTimeMillis();
// Log.w("ceshi", "onDrawFrame===");
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);// 清除屏幕和深度缓存
float[] mtx = new float[16];
mSurface.getTransformMatrix(mtx);
mCameraMatrix.draw(mtx);
// Set the camera position (View matrix)
Matrix.setLookAtM(mVMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1f, 0f);
// Calculate the projection and view transformation
Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0);
mPointsMatrix.draw(mMVPMatrix);
if (isDebug) {
runOnUiThread(new Runnable() {
@Override
public void run() {
final long endTime = System.currentTimeMillis() - actionTime;
debugPrinttext.setText("printTime: " + endTime);
}
});
}
mSurface.updateTexImage();// 更新image,会调用onFrameAvailable方法
if (isStartRecorder) {
flip = !flip;
if (flip) { // ~30fps
synchronized (this) {
// mMediaHelper.frameAvailable(mtx);
mMediaHelper.frameAvailable(mtx);
}
}
}
}
private RectF calRect(Rect rect, float width, float height) {
float top = 1 - (rect.top * 1.0f / height) * 2;
float left = (rect.left * 1.0f / width) * 2 - 1;
float right = (rect.right * 1.0f / width) * 2 - 1;
float bottom = 1 - (rect.bottom * 1.0f / height) * 2;
RectF rectf = new RectF();
rectf.top = top;
rectf.left = left;
rectf.right = right;
rectf.bottom = bottom;
Log.d("ceshi", "calRect: " + rectf);
return rectf;
}
private FloatBuffer calRectPostion(Rect rect, float width, float height) {
float top = 1 - (rect.top * 1.0f / height) * 2;
float left = (rect.left * 1.0f / width) * 2 - 1;
float right = (rect.right * 1.0f / width) * 2 - 1;
float bottom = 1 - (rect.bottom * 1.0f / height) * 2;
// 左上角
float x1 = -top;
float y1 = left;
// 右下角
float x2 = -bottom;
float y2 = right;
if (isBackCamera) {
y1 = -y1;
y2 = -y2;
}
float[] tempFace = {
x1, y2, 0.0f,
x1, y1, 0.0f,
x2, y1, 0.0f,
x2, y2, 0.0f,
};
FloatBuffer buffer = mCameraMatrix.floatBufferUtil(tempFace);
return buffer;
}
// 照片 90压缩比
public static String Bitmap2BASE64(Bitmap bm) {
if (bm == null) {
return "";
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 50, baos);
String imageBuffer = "";
String imageBuffers = new String(Base64.encode(baos.toByteArray(), Base64.DEFAULT)); // 进行Base64编码
// 分两次encode照片数据,防止图片过大内存溢出
int i = imageBuffers.length() / 2;
imageBuffer = URLEncoder.encode(imageBuffers.substring(0, i));
imageBuffer += URLEncoder.encode(imageBuffers.substring(i, imageBuffers.length()));
return imageBuffer;
}
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。