当前位置:   article > 正文

face++矿视的opengl坐标系CameraMatrix适配普通手机和定制设备,以及生成图片流后转换图片方向_minfacesize roi_left

minfacesize roi_left
  1. package com.facepp.xbdemo.util;
  2. import android.opengl.GLES11Ext;
  3. import android.opengl.GLES20;
  4. import android.opengl.Matrix;
  5. import android.util.Log;
  6. import java.nio.ByteBuffer;
  7. import java.nio.ByteOrder;
  8. import java.nio.FloatBuffer;
  9. import java.nio.IntBuffer;
  10. import java.nio.ShortBuffer;
  11. public class CameraMatrix {
  12. // vertex着色器code
  13. private final String vertexShaderCode = "attribute vec4 vPosition;"
  14. + "attribute vec2 inputTextureCoordinate;"
  15. + "varying vec2 textureCoordinate;" + "void main()" + "{"
  16. + "gl_Position = vPosition; gl_PointSize = 10.0;"
  17. + "textureCoordinate = inputTextureCoordinate;" + "}";
  18. // fragment着色器code
  19. private final String fragmentShaderCode = "#extension GL_OES_EGL_image_external : require\n"
  20. + "precision mediump float;"
  21. + "varying vec2 textureCoordinate;\n"
  22. + "uniform samplerExternalOES s_texture;\n"
  23. + "void main() {"
  24. + " gl_FragColor = texture2D( s_texture, textureCoordinate );\n"
  25. + "}";
  26. private FloatBuffer vertexBuffer, textureVerticesBuffer;
  27. private ShortBuffer drawListBuffer;
  28. private final int mProgram;
  29. private String mtype;
  30. // // private FloatBuffer triangleVB;
  31. // public ArrayList<ArrayList> points = new ArrayList<ArrayList>();
  32. private short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices
  33. // (命令绘制顶点)
  34. // number of coordinates per vertex in this array (顶点坐标数)
  35. private static final int COORDS_PER_VERTEX = 2;
  36. // 顶点步幅
  37. private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per
  38. // vertex
  39. // 直角坐标系 OLD 用于普通手机相机
  40. // static float squareCoords[] = {
  41. // -1.0f, 1.0f,
  42. // -1.0f, -1.0f,
  43. // 1.0f, -1.0f,
  44. // 1.0f, 1.0f, };
  45. // 直角坐标系 OLD左偏转90° 适配执法仪后置摄像头
  46. // static float squareCoords[] = {
  47. // -1.0f, -1.0f,
  48. // 1.0f, -1.0f,
  49. // 1.0f, 1.0f,
  50. // -1.0f, 1.0f, };
  51. private final float squareCoords[];
  52. // 结构顶点(8个数字表示了4个点x,y的位置.大小在0-1之间)
  53. // static float textureVertices[] = {
  54. // 1.0f, 1.0f,
  55. // 1.0f, 0.0f,
  56. // 0.0f, 0.0f,
  57. // 0.0f, 1.0f, };
  58. //OLD
  59. static float textureVertices[] = {
  60. 0.0f, 1.0f,
  61. 1.0f, 1.0f,
  62. 1.0f, 0.0f,
  63. 0.0f, 0.0f, };
  64. private int mTextureID;
  65. static float LineCoords[] = { 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f };
  66. private final int VertexCount = LineCoords.length / 3;
  67. public CameraMatrix(int textureID) {
  68. mtype = OpenGLUtil.getMobileMode();
  69. Log.e("wyd1","mtype="+mtype);
  70. if ("Z1".equals(mtype) || "HisenseZ1".equals(mtype) || "Hisense Z1".equals(mtype)) {
  71. squareCoords = new float[]{
  72. -1.0f, -1.0f,
  73. 1.0f, -1.0f,
  74. 1.0f, 1.0f,
  75. -1.0f, 1.0f,};
  76. Log.e("wyd1","mtype执法仪="+mtype);
  77. }else {
  78. squareCoords = new float[]{
  79. -1.0f, 1.0f,
  80. -1.0f, -1.0f,
  81. 1.0f, -1.0f,
  82. 1.0f, 1.0f, };
  83. Log.e("wyd1","mtype普通手机="+mtype);
  84. }
  85. this.mTextureID = textureID;
  86. // initialize vertex byte buffer for shape coordinates(初始化顶点字节缓冲区形状坐标)
  87. vertexBuffer = floatBufferUtil(squareCoords);
  88. // initialize byte buffer for the draw list (绘制列表初始化字节缓冲区)
  89. drawListBuffer = ShortBufferUtil(drawOrder);
  90. // initialize textureVertices byte buffer for shape
  91. // coordinates(初始化结构顶点字节缓冲区形状坐标)
  92. textureVerticesBuffer = floatBufferUtil(textureVertices);
  93. mProgram = GLES20.glCreateProgram(); // create empty OpenGL ES Program
  94. // 拿出两个着色器 顶点着色器和碎片着色器
  95. int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
  96. GLES20.glAttachShader(mProgram, vertexShader); // add the vertex shader
  97. int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER,
  98. fragmentShaderCode);
  99. GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment
  100. // shader to program
  101. GLES20.glLinkProgram(mProgram); // creates OpenGL ES program executables
  102. }
  103. /**
  104. * 绘制:
  105. *
  106. * 我们在 onDrawFrame 回调中执行绘制操作,绘制的过程其实就是为 shader 代码变量赋值,并调用绘制命令的过程:
  107. */
  108. public void draw(float[] mtx) {
  109. // to program
  110. GLES20.glUseProgram(mProgram);
  111. GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
  112. GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mTextureID);
  113. // get handle to vertex shader's vPosition member
  114. // (顶点着色器的vPosition成员得到处理)
  115. int mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
  116. // Enable a handle to the triangle vertices(使一个句柄三角形顶点)
  117. GLES20.glEnableVertexAttribArray(mPositionHandle);
  118. // Prepare the <insert shape here> coordinate data (准备<插入形状这里>坐标数据)
  119. GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
  120. GLES20.GL_FLOAT, false, vertexStride, vertexBuffer);
  121. int mTextureCoordHandle = GLES20.glGetAttribLocation(mProgram,
  122. "inputTextureCoordinate");
  123. GLES20.glEnableVertexAttribArray(mTextureCoordHandle);
  124. //照相机镜像
  125. textureVerticesBuffer.clear();
  126. textureVerticesBuffer.put(transformTextureCoordinates(textureVertices,
  127. mtx));
  128. textureVerticesBuffer.position(0);
  129. GLES20.glVertexAttribPointer(mTextureCoordHandle, COORDS_PER_VERTEX,
  130. GLES20.GL_FLOAT, false, vertexStride, textureVerticesBuffer);
  131. GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length,
  132. GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
  133. // for (int i = 0; i < points.size(); i++) {
  134. // ArrayList<FloatBuffer> triangleVBList = points.get(i);
  135. // for (int j = 0; j < triangleVBList.size(); j++) {
  136. // FloatBuffer fb = triangleVBList.get(j);
  137. // GLES20.glVertexAttribPointer(mPositionHandle, 3,
  138. // GLES20.GL_FLOAT, false, 0, fb);
  139. // GLES20.glEnableVertexAttribArray(mPositionHandle);
  140. // // Draw the point
  141. // GLES20.glDrawArrays(GLES20.GL_POINTS, 0, 1);
  142. // }
  143. // }
  144. // Disable vertex array
  145. GLES20.glDisableVertexAttribArray(mPositionHandle);
  146. GLES20.glDisableVertexAttribArray(mTextureCoordHandle);
  147. }
  148. public boolean isDraw = false;
  149. /**
  150. * 图像旋转
  151. */
  152. private float[] transformTextureCoordinates(float[] coords, float[] matrix) {
  153. float[] result = new float[coords.length];
  154. float[] vt = new float[4];
  155. for (int i = 0; i < coords.length; i += 2) {
  156. float[] v = { coords[i], coords[i + 1], 0, 1 };
  157. // for (int j = 0; j < v.length; j ++) {
  158. // Log.w("ceshi", "v[" + j + "]======" + coords[j]);
  159. // }
  160. Matrix.multiplyMV(vt, 0, matrix, 0, v, 0);
  161. result[i] = vt[0];// x轴镜像
  162. // result[i + 1] = vt[1];y轴镜像
  163. result[i + 1] = coords[i + 1];
  164. }
  165. //
  166. // for (int i = 0; i < coords.length; i ++) {
  167. // Log.w("ceshi", "coords[" + i + "]======" + coords[i]);
  168. // }
  169. //
  170. // for (int i = 0; i < result.length / 2; i ++) {
  171. // Log.w("ceshi", "result[" + i + "]======" + result[i]);
  172. // }
  173. // [0.0, 1.0, 1.0, 1.0]; v
  174. // [0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0]; coords
  175. // [1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0]; result
  176. return result;
  177. }
  178. /**
  179. * 加载 著色器
  180. */
  181. private int loadShader(int type, String shaderCode) {
  182. // create a vertex shader type (GLES20.GL_VERTEX_SHADER)
  183. // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
  184. int shader = GLES20.glCreateShader(type);
  185. // add the source code to the shader and compile it
  186. GLES20.glShaderSource(shader, shaderCode);
  187. GLES20.glCompileShader(shader);
  188. return shader;
  189. }
  190. // 定义一个工具方法,将int[]数组转换为OpenGL ES所需的IntBuffer
  191. private IntBuffer intBufferUtil(int[] arr) {
  192. // 初始化ByteBuffer,长度为arr数组的长度*4,因为一个int占4个字节
  193. ByteBuffer qbb = ByteBuffer.allocateDirect(arr.length * 4);
  194. // 数组排列用nativeOrder
  195. qbb.order(ByteOrder.nativeOrder());
  196. IntBuffer mBuffer = qbb.asIntBuffer();
  197. mBuffer.put(arr);
  198. mBuffer.position(0);
  199. return mBuffer;
  200. }
  201. // 定义一个工具方法,将float[]数组转换为OpenGL ES所需的FloatBuffer
  202. public FloatBuffer floatBufferUtil(float[] arr) {
  203. // 初始化ByteBuffer,长度为arr数组的长度*4,因为一个int占4个字节
  204. ByteBuffer qbb = ByteBuffer.allocateDirect(arr.length * 4);
  205. // 数组排列用nativeOrder
  206. qbb.order(ByteOrder.nativeOrder());
  207. FloatBuffer mBuffer = qbb.asFloatBuffer();
  208. mBuffer.put(arr);
  209. mBuffer.position(0);
  210. return mBuffer;
  211. }
  212. // 定义一个工具方法,将Short[]数组转换为OpenGL ES所需的ShortBuffer
  213. private ShortBuffer ShortBufferUtil(short[] arr) {
  214. ByteBuffer dlb = ByteBuffer.allocateDirect(arr.length * 2);
  215. dlb.order(ByteOrder.nativeOrder());
  216. ShortBuffer buffer = dlb.asShortBuffer();
  217. buffer.put(arr);
  218. buffer.position(0);
  219. return buffer;
  220. }
  221. // 定义一个工具方法,将Short[]数组转换为OpenGL ES所需的ShortBuffer
  222. private ByteBuffer ByteBufferUtil(Byte[] arr) {
  223. ByteBuffer dlb = ByteBuffer.allocateDirect(arr.length);
  224. // dlb.order(ByteOrder.nativeOrder());
  225. // ByteBuffer buffer = dlb.asShortBuffer();
  226. // buffer.put(arr);
  227. dlb.position(0);
  228. return dlb;
  229. }
  230. }

 

 

 

 

 

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;
    }
}
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/46078
推荐阅读
相关标签
  

闽ICP备14008679号