[
  {
    "path": "Camera/CameraV1/.gitignore",
    "content": "*.iml\n.gradle\n/local.properties\n/.idea/workspace.xml\n/.idea/libraries\n.DS_Store\n/build\n/captures\n.externalNativeBuild\n"
  },
  {
    "path": "Camera/CameraV1/README.md",
    "content": "This is a CameraV1 Demo,it has preview、switch camera、take picture function.\n"
  },
  {
    "path": "Camera/CameraV1/app/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "Camera/CameraV1/app/build.gradle",
    "content": "apply plugin: 'com.android.application'\n\nandroid {\n    compileSdkVersion 25\n    buildToolsVersion \"25.0.2\"\n    defaultConfig {\n        applicationId \"com.lb377463323.camera1\"\n        minSdkVersion 15\n        targetSdkVersion 25\n        versionCode 1\n        versionName \"1.0\"\n        testInstrumentationRunner \"android.support.test.runner.AndroidJUnitRunner\"\n    }\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n        }\n    }\n}\n\ndependencies {\n    compile fileTree(include: ['*.jar'], dir: 'libs')\n    compile 'com.android.support:appcompat-v7:25.1.1'\n}\n"
  },
  {
    "path": "Camera/CameraV1/app/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in /home/liubing/Android/Sdk/tools/proguard/proguard-android.txt\n# You can edit the include path and order by changing the proguardFiles\n# directive in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# Add any project specific keep options here:\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n"
  },
  {
    "path": "Camera/CameraV1/app/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n          package=\"com.lb377463323.camera1\">\n\n    <uses-permission android:name=\"android.permission.CAMERA\"/>\n    <uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\"/>\n\n    <application\n        android:allowBackup=\"true\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:supportsRtl=\"true\"\n        android:theme=\"@style/Theme.AppCompat.NoActionBar\">\n        <activity android:name=\"com.lb377463323.camera1.MainActivity\"\n            android:configChanges=\"orientation|keyboardHidden|screenSize\"\n            android:screenOrientation=\"portrait\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\"/>\n\n                <category android:name=\"android.intent.category.LAUNCHER\"/>\n            </intent-filter>\n        </activity>\n    </application>\n\n</manifest>"
  },
  {
    "path": "Camera/CameraV1/app/src/main/java/com/lb377463323/camera1/MainActivity.java",
    "content": "package com.lb377463323.camera1;\n\nimport android.content.Context;\nimport android.content.pm.PackageManager;\nimport android.graphics.Bitmap;\nimport android.graphics.BitmapFactory;\nimport android.graphics.Color;\nimport android.graphics.Matrix;\nimport android.graphics.SurfaceTexture;\nimport android.hardware.Camera;\nimport android.os.Bundle;\nimport android.os.Environment;\nimport android.os.Process;\nimport android.support.v7.app.AppCompatActivity;\nimport android.util.Log;\nimport android.view.Gravity;\nimport android.view.TextureView;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.AdapterView;\nimport android.widget.BaseAdapter;\nimport android.widget.Button;\nimport android.widget.ListView;\nimport android.widget.PopupWindow;\nimport android.widget.TextView;\n\nimport java.io.BufferedOutputStream;\nimport java.io.File;\nimport java.io.FileNotFoundException;\nimport java.io.FileOutputStream;\nimport java.io.IOException;\nimport java.text.SimpleDateFormat;\nimport java.util.ArrayList;\nimport java.util.Date;\nimport java.util.List;\n\npublic class MainActivity extends AppCompatActivity implements TextureView.SurfaceTextureListener, View.OnClickListener, AdapterView.OnItemClickListener{\n    private String TAG = \"MainActivity\";\n    public static final String STORAGE_PATH = Environment.getExternalStorageDirectory().toString();\n\n    private Camera mCamera;\n    private TextureView mTextureView;\n    private int mCameraId;\n    private int mCameraNum;\n    private Button mCaptureButton;\n    private Button mSwitchCamButton;\n    private Button mPictureSizeButton;\n    private PopupWindow mPreviewPopupWindow;\n    private PopupWindow mPicturePopupWindow;\n    private Camera.Parameters mParameters;\n    private List<Camera.Size> mSupportedPreSizeList;\n    private List<Camera.Size> mSupportedPicSizeList;\n    private List<String> mPreviewSizeList;\n    private List<String> mPictureSizeList;\n    private ListView mPictureListView;\n    private MyAdapter mPictureAdapter;\n    private int mCaptureWidth;\n    private int mCaptureHeight;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_main);\n        mTextureView = (TextureView) findViewById(R.id.camera_preview);\n        mCaptureButton = (Button) findViewById(R.id.btn_capture);\n        mSwitchCamButton = (Button) findViewById(R.id.btn_switchCam);\n        mPictureSizeButton = (Button) findViewById(R.id.btn_pictureSize);\n        mCaptureButton.setOnClickListener(this);\n        mSwitchCamButton.setOnClickListener(this);\n        mPictureSizeButton.setOnClickListener(this);\n\n        if(checkCameraHardware(this)){\n            mCameraNum = Camera.getNumberOfCameras();\n            Log.i(TAG, \"Camera Number: \" + mCameraNum);\n            mTextureView.setSurfaceTextureListener(this);\n        }else {\n            Log.i(TAG, \"Has not Camera!\");\n        }\n    }\n\n    @Override\n    protected void onResume() {\n        super.onResume();\n        requestCamera(mCameraId);\n        initSizeList();\n        initParameters();\n        initPopupWindow();\n    }\n\n    //Check whether the device has a camera\n    private boolean checkCameraHardware(Context context){\n        if(context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){\n            return true;//has Camera\n        }else {\n            return false;// has not Camera\n        }\n    }\n\n    private void setPreviewTexture(SurfaceTexture surfaceTexture) {\n        if (mCamera != null) {\n            try {\n                mCamera.setPreviewTexture(surfaceTexture);\n            } catch (IOException e) {\n                e.printStackTrace();\n            }\n        }\n    }\n\n    @Override\n    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {\n        setPreviewTexture(surface);\n        setDisplayOrientation(90);\n        startPreview();\n        Log.i(TAG, \"onSurfaceTextureAvailable: size:\" + width +\",\" + height);\n    }\n\n    @Override\n    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {\n\n    }\n\n    @Override\n    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {\n        return false;\n    }\n\n    @Override\n    public void onSurfaceTextureUpdated(SurfaceTexture surface) {\n\n    }\n\n    @Override\n    public void onClick(View v) {\n        switch (v.getId()){\n            case R.id.btn_capture:\n                takePicture();\n                break;\n            case R.id.btn_switchCam:\n                switchCamera();\n                break;\n            case R.id.btn_pictureSize:\n                showPopupWindow(mPicturePopupWindow, mPictureSizeButton);\n                break;\n            default:\n                break;\n        }\n    }\n\n    public void takePicture(){\n        if (mCamera != null){\n            mCamera.takePicture(null, null, mPictureCallback);\n        }\n    }\n\n    public void switchCamera(){\n        if (mCameraNum > 1){\n            mCameraId = mCameraId == Camera.CameraInfo.CAMERA_FACING_BACK ?\n                    Camera.CameraInfo.CAMERA_FACING_FRONT : Camera.CameraInfo.CAMERA_FACING_BACK;\n            stopPreview();\n            closeCamera();\n\n            requestCamera(mCameraId);\n            initSizeList();\n            for (int i = 0; i < mPreviewSizeList.size(); i++) {\n                Log.i(TAG, \"preview size \" + i + \" :\" + mPreviewSizeList.get(i));\n            }\n\n            for (int j = 0; j < mPictureSizeList.size(); j++) {\n                Log.i(TAG, \"picture size \" + j + \" :\" + mPictureSizeList.get(j));\n            }\n            initParameters();\n            mPictureAdapter.notifyDataSetChanged();\n            setDisplayOrientation(90);\n            setPreviewTexture(mTextureView.getSurfaceTexture());\n            startPreview();\n            Log.i(TAG, \"Camera has switched！\");\n        }else {\n            Log.i(TAG, \"This device does not support switch camera\");\n        }\n    }\n\n    private Camera.ErrorCallback mErrorCallback = new Camera.ErrorCallback() {\n        @Override\n        public void onError(int error, Camera camera) {\n            Log.e(TAG, \"onError: got camera error callback: \" + error);\n            if (error == Camera.CAMERA_ERROR_SERVER_DIED) {\n                android.os.Process.killProcess(Process.myPid());\n            }\n        }\n    };\n\n    private Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {\n        @Override\n        public void onPictureTaken(final byte[] data, Camera camera) {\n            new Thread(new Runnable() {\n                @Override\n                public void run() {\n                    String path = STORAGE_PATH + \"/DCIM\" + \"/CameraV1\";\n                    writeFile(path, data);\n                }\n            }, \"captureThread\").start();\n            startPreview();\n        }\n    };\n\n    public void writeFile(String path, byte[] data) {\n        Bitmap bitmap = null;\n        if (data != null){\n            bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);\n        }\n\n        if (bitmap != null){\n            Matrix matrix = new Matrix();\n            if (mCameraId == Camera.CameraInfo.CAMERA_FACING_BACK) {\n                matrix.postRotate(90);\n            }else if (mCameraId == Camera.CameraInfo.CAMERA_FACING_FRONT){\n                matrix.postRotate(90);\n                matrix.postScale(1, -1);\n            }\n            Bitmap rotateBmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),\n                    bitmap.getHeight(), matrix,false);\n            saveBmp2SD(path, rotateBmp);\n            rotateBmp.recycle();\n        }\n    }\n\n    private void saveBmp2SD(String path, Bitmap bitmap){\n        File file = new File(path);\n        if (!file.exists()){\n            file.mkdir();\n        }\n        String timeStamp = new SimpleDateFormat(\"yyyyMMdd_HHmmss\").format(new Date());\n        String fileName = path + \"/\" + \"IMG_\" + timeStamp + \".jpg\";\n        try {\n            FileOutputStream fos = new FileOutputStream(fileName);\n            BufferedOutputStream bos = new BufferedOutputStream(fos);\n            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);\n            bos.flush();\n            bos.close();\n            Log.i(TAG, \"Take picture success!\");\n        } catch (FileNotFoundException e) {\n            e.printStackTrace();\n            Log.e(TAG, \"The save file for take picture is not exists!\");\n        } catch (IOException e) {\n            e.printStackTrace();\n            Log.e(TAG, \"Take picture fail!\");\n        }\n    }\n\n    private void setDisplayOrientation(int degree){\n        if (mCamera != null) {\n            mCamera.setDisplayOrientation(degree);\n        }\n        Log.i(TAG, \"Set display orientation is : \" + degree);\n    }\n\n    private void requestCamera(int mCameraId) {\n        openCamera(mCameraId);\n    }\n\n    private void openCamera(int cameraId){\n        try{\n            if (mCamera == null) {\n                mCamera = Camera.open(cameraId);\n                Log.i(TAG, \"Camera has opened, cameraId is \" + cameraId);\n            }\n        }catch (Exception e){\n            Log.e(TAG, \"Open Camera has exception!\");\n        }\n    }\n\n    private void startPreview(){\n        if (mCamera != null) {\n            mCamera.setErrorCallback(mErrorCallback);\n            mCamera.startPreview();\n            Log.i(TAG, \"Camera Preview has started!\");\n        }\n    }\n\n    private void stopPreview() {\n        if (mCamera != null){\n            mCamera.stopPreview();\n            Log.i(TAG, \"Camera Preview has stopped!\");\n        }\n    }\n\n    private void closeCamera() {\n        if (mCamera != null){\n            mCamera.setErrorCallback(null);\n            mCamera.release();\n            mCamera = null;\n            Log.i(TAG, \"Camera has closed!\");\n        }\n    }\n\n    @Override\n    protected void onPause() {\n        super.onPause();\n        stopPreview();\n        closeCamera();\n    }\n\n    private void initSizeList() {\n        mParameters = getParameters();\n        mSupportedPreSizeList = getSupportedPreviewSizes(mParameters);\n        mSupportedPicSizeList = getSupportedPictureSizes(mParameters);\n    }\n\n    private void initParameters() {\n        if (mSupportedPreSizeList != null && mSupportedPicSizeList != null) {\n            mParameters.setPreviewSize(mSupportedPreSizeList.get(mSupportedPreSizeList.size() - 1).width,\n                    mSupportedPreSizeList.get(mSupportedPreSizeList.size() - 1).height);\n            Log.i(TAG, \"initParameters: previewSize: \" + mSupportedPreSizeList.get(mSupportedPreSizeList.size() - 1).width +\n                    \",\" + mSupportedPreSizeList.get(mSupportedPreSizeList.size() - 1).height);\n            mCaptureWidth = mSupportedPicSizeList.get(mSupportedPicSizeList.size() - 1).width;\n            mCaptureHeight = mSupportedPicSizeList.get(mSupportedPicSizeList.size() - 1).height;\n            mParameters.setPictureSize(mCaptureWidth, mCaptureHeight);\n            Log.i(TAG, \"initParameters: pictureSize: \" + mCaptureWidth + \",\" + mCaptureHeight);\n            setParameters();\n        }\n    }\n\n    private void initPopupWindow() {\n        initPicturePopupWindow();\n    }\n\n    private void initPicturePopupWindow() {\n        mPictureAdapter = new MyAdapter(mPictureSizeList);\n        mPictureListView = new ListView(this);\n        mPictureListView.setId(R.id.pictureId);\n        mPictureListView.setAdapter(mPictureAdapter);\n        if (mPicturePopupWindow == null) {\n            mPicturePopupWindow = new PopupWindow(mPictureListView, 320, 320,true);\n        }\n        mPictureListView.setOnItemClickListener(this);\n    }\n\n    private void showPopupWindow(PopupWindow popupWindow, View view) {\n        if (popupWindow != null && view != null && !popupWindow.isShowing()) {\n            int[] location = new int[2];\n            view.getLocationOnScreen(location);\n            popupWindow.showAtLocation(view, Gravity.NO_GRAVITY, location[0], location[1] - popupWindow.getHeight());\n        } else {\n            if (popupWindow != null) {\n                popupWindow.dismiss();\n            }\n        }\n    }\n\n    class MyAdapter extends BaseAdapter {\n        List<String> sizeList = new ArrayList<>();\n\n        public MyAdapter(List<String> list) {\n            this.sizeList = list;\n        }\n\n        @Override\n        public int getCount() {\n            return sizeList.size();\n        }\n\n        @Override\n        public Object getItem(int position) {\n            return sizeList.get(position);\n        }\n\n        @Override\n        public long getItemId(int position) {\n            return position;\n        }\n\n        @Override\n        public View getView(int position, View convertView, ViewGroup parent) {\n            TextView textView = new TextView(MainActivity.this);\n            textView.setTextSize(18);\n            textView.setTextColor(Color.rgb(255, 255, 0));\n            textView.setText(sizeList.get(position));\n            return textView;\n        }\n    }\n\n    private Camera.Parameters getParameters() {\n        if (mCamera != null) {\n            return mCamera.getParameters();\n        }\n        return null;\n    }\n\n    private void setParameters() {\n        if(mCamera != null && mParameters != null) {\n            mCamera.setParameters(mParameters);\n        }\n    }\n\n    private List<Camera.Size> getSupportedPreviewSizes(Camera.Parameters parameters) {\n        if (parameters == null) {\n            return null;\n        }\n        if (mPreviewSizeList == null) {\n            mPreviewSizeList = new ArrayList<>();\n        } else {\n            mPreviewSizeList.clear();\n        }\n        mSupportedPreSizeList = new ArrayList<>();\n        for (Camera.Size size : parameters.getSupportedPreviewSizes()) {\n            if (equalsRate(size, 1.777f)) {\n                mSupportedPreSizeList.add(size);\n            }\n        }\n        for (Camera.Size size : mSupportedPreSizeList) {\n            mPreviewSizeList.add(size.width + \"×\" + size.height);\n        }\n        return mSupportedPreSizeList;\n    }\n\n\n    private List<Camera.Size> getSupportedPictureSizes(Camera.Parameters parameters) {\n        if (parameters == null) {\n            return null;\n        }\n        if (mPictureSizeList == null) {\n            mPictureSizeList = new ArrayList<>();\n        } else {\n            mPictureSizeList.clear();\n        }\n        mSupportedPicSizeList = new ArrayList<>();\n        for (Camera.Size size : parameters.getSupportedPictureSizes()) {\n            if(equalsRate(size, 1.777f)) {\n                mSupportedPicSizeList.add(size);\n            }\n        }\n        for (Camera.Size size : mSupportedPicSizeList) {\n            mPictureSizeList.add(size.width + \"×\" + size.height);\n        }\n        return mSupportedPicSizeList;\n    }\n\n    @Override\n    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {\n        switch (parent.getId()) {\n            case R.id.pictureId:\n                Log.i(TAG, \"onItemClick: PictureSize: \" + mPictureSizeList.get(position));\n                setCaptureSize(mSupportedPicSizeList.get(position).width,\n                        mSupportedPicSizeList.get(position).height);\n                mPicturePopupWindow.dismiss();\n                break;\n            default:\n                break;\n        }\n    }\n\n    private void setPreviewSize(float rate) {\n        if (!equalsRate(mParameters.getPreviewSize(), rate)) {\n            mParameters.setPreviewSize(mSupportedPreSizeList.get(mSupportedPreSizeList.size() - 1).width,\n                    mSupportedPreSizeList.get(mSupportedPreSizeList.size() - 1).height);\n            Log.i(TAG, \"setPreviewSize: changed: \" + mSupportedPreSizeList.get(mSupportedPreSizeList.size() - 1).width +\n                    \"×\" + mSupportedPreSizeList.get(mSupportedPreSizeList.size() - 1).height);\n            setParameters();\n            stopPreview();\n            startPreview();\n        } else {\n            return;\n        }\n    }\n\n    private void setCaptureSize(int captureWidth, int captureHeight) {\n        this.mCaptureWidth = captureWidth;\n        this.mCaptureHeight = captureHeight;\n        mParameters.setPictureSize(mCaptureWidth, mCaptureHeight);\n        if (mCamera != null) {\n            setParameters();\n        }\n        setPreviewSize((float) captureWidth / (float) captureHeight);\n    }\n\n    private boolean equalsRate(Camera.Size size, float rate){\n        float f = (float)size.width / (float) size.height;\n        if (Math.abs(f - rate) <= 0.1f) {\n            return true;\n        } else {\n            return false;\n        }\n    }\n}\n"
  },
  {
    "path": "Camera/CameraV1/app/src/main/res/layout/activity_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/activity_main\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\"\n    tools:context=\"com.lb377463323.camera1.MainActivity\">\n\n    <TextureView\n        android:id=\"@+id/camera_preview\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"/>\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignParentBottom=\"true\"\n        android:orientation=\"horizontal\">\n        <Button\n            android:id=\"@+id/btn_switchCam\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_weight=\"1\"\n            android:text=\"切换\"/>\n        <Button\n            android:id=\"@+id/btn_capture\"\n            android:text=\"拍照\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_weight=\"1\"/>\n        <Button\n            android:id=\"@+id/btn_pictureSize\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_weight=\"1\"\n            android:text=\"拍照尺寸\"/>\n    </LinearLayout>\n\n\n</RelativeLayout>\n"
  },
  {
    "path": "Camera/CameraV1/app/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#3F51B5</color>\n    <color name=\"colorPrimaryDark\">#303F9F</color>\n    <color name=\"colorAccent\">#FF4081</color>\n</resources>\n"
  },
  {
    "path": "Camera/CameraV1/app/src/main/res/values/dimens.xml",
    "content": "<resources>\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"activity_horizontal_margin\">16dp</dimen>\n    <dimen name=\"activity_vertical_margin\">16dp</dimen>\n</resources>\n"
  },
  {
    "path": "Camera/CameraV1/app/src/main/res/values/ids.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <item name=\"pictureId\" type=\"id\"></item>\n</resources>"
  },
  {
    "path": "Camera/CameraV1/app/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">CameraV1</string>\n</resources>\n"
  },
  {
    "path": "Camera/CameraV1/app/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar\">\n        <!-- Customize your theme here. -->\n        <item name=\"colorPrimary\">@color/colorPrimary</item>\n        <item name=\"colorPrimaryDark\">@color/colorPrimaryDark</item>\n        <item name=\"colorAccent\">@color/colorAccent</item>\n    </style>\n\n</resources>\n"
  },
  {
    "path": "Camera/CameraV1/app/src/main/res/values-w820dp/dimens.xml",
    "content": "<resources>\n    <!-- Example customization of dimensions originally defined in res/values/dimens.xml\n         (such as screen margins) for screens with more than 820dp of available width. This\n         would include 7\" and 10\" devices in landscape (~960dp and ~1280dp respectively). -->\n    <dimen name=\"activity_horizontal_margin\">64dp</dimen>\n</resources>\n"
  },
  {
    "path": "Camera/CameraV1/build.gradle",
    "content": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n    repositories {\n        jcenter()\n    }\n    dependencies {\n        classpath 'com.android.tools.build:gradle:2.3.0'\n\n        // NOTE: Do not place your application dependencies here; they belong\n        // in the individual module build.gradle files\n    }\n}\n\nallprojects {\n    repositories {\n        jcenter()\n    }\n}\n\ntask clean(type: Delete) {\n    delete rootProject.buildDir\n}\n"
  },
  {
    "path": "Camera/CameraV1/gradle/wrapper/gradle-wrapper.properties",
    "content": "#Wed Oct 21 11:34:03 PDT 2015\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-3.5-all.zip\n"
  },
  {
    "path": "Camera/CameraV1/gradle.properties",
    "content": "# Project-wide Gradle settings.\n\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will override*\n# any settings specified in this file.\n\n# For more details on how to configure your build environment visit\n# http://www.gradle.org/docs/current/userguide/build_environment.html\n\n# Specifies the JVM arguments used for the daemon process.\n# The setting is particularly useful for tweaking memory settings.\norg.gradle.jvmargs=-Xmx1536m\n\n# When configured, Gradle will run in incubating parallel mode.\n# This option should only be used with decoupled projects. More details, visit\n# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects\n# org.gradle.parallel=true\n"
  },
  {
    "path": "Camera/CameraV1/gradlew",
    "content": "#!/usr/bin/env bash\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS=\"\"\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn ( ) {\n    echo \"$*\"\n}\n\ndie ( ) {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\nesac\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done\n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules\nfunction splitJvmOpts() {\n    JVM_OPTS=(\"$@\")\n}\neval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\nJVM_OPTS[${#JVM_OPTS[*]}]=\"-Dorg.gradle.appname=$APP_BASE_NAME\"\n\nexec \"$JAVACMD\" \"${JVM_OPTS[@]}\" -classpath \"$CLASSPATH\" org.gradle.wrapper.GradleWrapperMain \"$@\"\n"
  },
  {
    "path": "Camera/CameraV1/gradlew.bat",
    "content": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem  Gradle startup script for Windows\n@rem\n@rem ##########################################################################\n\n@rem Set local scope for the variables with windows NT shell\nif \"%OS%\"==\"Windows_NT\" setlocal\n\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nset DEFAULT_JVM_OPTS=\n\nset DIRNAME=%~dp0\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\nset APP_BASE_NAME=%~n0\nset APP_HOME=%DIRNAME%\n\n@rem Find java.exe\nif defined JAVA_HOME goto findJavaFromJavaHome\n\nset JAVA_EXE=java.exe\n%JAVA_EXE% -version >NUL 2>&1\nif \"%ERRORLEVEL%\" == \"0\" goto init\n\necho.\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:findJavaFromJavaHome\nset JAVA_HOME=%JAVA_HOME:\"=%\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\n\nif exist \"%JAVA_EXE%\" goto init\n\necho.\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:init\n@rem Get command-line arguments, handling Windowz variants\n\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\nif \"%@eval[2+2]\" == \"4\" goto 4NT_args\n\n:win9xME_args\n@rem Slurp the command line arguments.\nset CMD_LINE_ARGS=\nset _SKIP=2\n\n:win9xME_args_slurp\nif \"x%~1\" == \"x\" goto execute\n\nset CMD_LINE_ARGS=%*\ngoto execute\n\n:4NT_args\n@rem Get arguments from the 4NT Shell from JP Software\nset CMD_LINE_ARGS=%$\n\n:execute\n@rem Setup the command line\n\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\n\n@rem Execute Gradle\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\n\n:end\n@rem End local scope for the variables with windows NT shell\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\n\n:fail\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\nrem the _cmd.exe /c_ return code!\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\nexit /b 1\n\n:mainEnd\nif \"%OS%\"==\"Windows_NT\" endlocal\n\n:omega\n"
  },
  {
    "path": "Camera/CameraV1/settings.gradle",
    "content": "include ':app'\n"
  },
  {
    "path": "Camera/CameraV2/.gitignore",
    "content": "*.iml\n.gradle\n/local.properties\n/.idea/workspace.xml\n/.idea/libraries\n.DS_Store\n/build\n/captures\n"
  },
  {
    "path": "Camera/CameraV2/app/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "Camera/CameraV2/app/build.gradle",
    "content": "apply plugin: 'com.android.application'\n\nandroid {\n    compileSdkVersion 25\n    buildToolsVersion \"25.0.2\"\n\n    defaultConfig {\n        applicationId \"com.lb377463323.camera2\"\n        minSdkVersion 21\n        targetSdkVersion 25\n        versionCode 1\n        versionName \"1.0\"\n    }\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n        }\n    }\n}\n\ndependencies {\n    compile fileTree(include: ['*.jar'], dir: 'libs')\n    compile 'com.android.support:appcompat-v7:25.1.1'\n    compile 'com.android.support:recyclerview-v7:25.1.1'\n}\n"
  },
  {
    "path": "Camera/CameraV2/app/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in E:\\AndroidSdk/tools/proguard/proguard-android.txt\n# You can edit the include path and order by changing the proguardFiles\n# directive in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# Add any project specific keep options here:\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n"
  },
  {
    "path": "Camera/CameraV2/app/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest package=\"com.lb377463323.camera2\"\n          xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\"/>\n    <uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\"/>\n    <uses-permission android:name=\"android.permission.CAMERA\"/>\n    <uses-feature android:name=\"android.hardware.camera2.full\" />\n\n    <application\n        android:allowBackup=\"true\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:supportsRtl=\"true\"\n        android:theme=\"@style/AppTheme\">\n        <activity android:name=\"com.lb377463323.camera2.MainActivity\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\"/>\n\n                <category android:name=\"android.intent.category.LAUNCHER\"/>\n            </intent-filter>\n        </activity>\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "Camera/CameraV2/app/src/main/java/com/lb377463323/camera2/MainActivity.java",
    "content": "package com.lb377463323.camera2;\n\nimport android.Manifest;\nimport android.app.Activity;\nimport android.content.Context;\nimport android.content.pm.PackageManager;\nimport android.graphics.ImageFormat;\nimport android.graphics.SurfaceTexture;\nimport android.hardware.camera2.CameraAccessException;\nimport android.hardware.camera2.CameraCaptureSession;\nimport android.hardware.camera2.CameraCharacteristics;\nimport android.hardware.camera2.CameraDevice;\nimport android.hardware.camera2.CameraManager;\nimport android.hardware.camera2.CameraMetadata;\nimport android.hardware.camera2.CaptureRequest;\nimport android.hardware.camera2.CaptureResult;\nimport android.hardware.camera2.TotalCaptureResult;\nimport android.hardware.camera2.params.StreamConfigurationMap;\nimport android.media.Image;\nimport android.media.ImageReader;\nimport android.os.Bundle;\nimport android.os.Environment;\nimport android.os.Handler;\nimport android.os.HandlerThread;\nimport android.support.v4.app.ActivityCompat;\nimport android.util.Size;\nimport android.util.SparseIntArray;\nimport android.view.Surface;\nimport android.view.TextureView;\nimport android.view.View;\nimport android.view.Window;\nimport android.view.WindowManager;\nimport android.widget.Toast;\n\nimport java.io.File;\nimport java.io.FileOutputStream;\nimport java.io.IOException;\nimport java.nio.ByteBuffer;\nimport java.text.SimpleDateFormat;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.Comparator;\nimport java.util.Date;\nimport java.util.List;\n\npublic class MainActivity extends Activity {\n    private static final SparseIntArray ORIENTATION = new SparseIntArray();\n\n    static {\n        ORIENTATION.append(Surface.ROTATION_0, 90);\n        ORIENTATION.append(Surface.ROTATION_90, 0);\n        ORIENTATION.append(Surface.ROTATION_180, 270);\n        ORIENTATION.append(Surface.ROTATION_270, 180);\n    }\n\n    private String mCameraId;\n    private Size mPreviewSize;\n    private Size mCaptureSize;\n    private HandlerThread mCameraThread;\n    private Handler mCameraHandler;\n    private CameraDevice mCameraDevice;\n    private TextureView mTextureView;\n    private ImageReader mImageReader;\n    private CaptureRequest.Builder mCaptureRequestBuilder;\n    private CaptureRequest mCaptureRequest;\n    private CameraCaptureSession mCameraCaptureSession;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n\n        //全屏无状态栏\n        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);\n        requestWindowFeature(Window.FEATURE_NO_TITLE);\n\n        setContentView(R.layout.activity_main);\n        mTextureView = (TextureView) findViewById(R.id.textureView);\n    }\n\n    @Override\n    protected void onResume() {\n        super.onResume();\n        startCameraThread();\n        if (!mTextureView.isAvailable()) {\n            mTextureView.setSurfaceTextureListener(mTextureListener);\n        } else {\n            startPreview();\n        }\n    }\n\n    private void startCameraThread() {\n        mCameraThread = new HandlerThread(\"CameraThread\");\n        mCameraThread.start();\n        mCameraHandler = new Handler(mCameraThread.getLooper());\n    }\n\n    private TextureView.SurfaceTextureListener mTextureListener = new TextureView.SurfaceTextureListener() {\n        @Override\n        public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {\n            //当SurefaceTexture可用的时候，设置相机参数并打开相机\n            setupCamera(width, height);\n            openCamera();\n        }\n\n        @Override\n        public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {\n\n        }\n\n        @Override\n        public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {\n            return false;\n        }\n\n        @Override\n        public void onSurfaceTextureUpdated(SurfaceTexture surface) {\n\n        }\n    };\n\n    private void setupCamera(int width, int height) {\n        //获取摄像头的管理者CameraManager\n        CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);\n        try {\n            //遍历所有摄像头\n            for (String cameraId : manager.getCameraIdList()) {\n                CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);\n                Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);\n                //此处默认打开后置摄像头\n                if (facing != null && facing == CameraCharacteristics.LENS_FACING_FRONT)\n                    continue;\n                //获取StreamConfigurationMap，它是管理摄像头支持的所有输出格式和尺寸\n                StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);\n                assert map != null;\n                //根据TextureView的尺寸设置预览尺寸\n                mPreviewSize = getOptimalSize(map.getOutputSizes(SurfaceTexture.class), width, height);\n                //获取相机支持的最大拍照尺寸\n                mCaptureSize = Collections.max(Arrays.asList(map.getOutputSizes(ImageFormat.JPEG)), new Comparator<Size>() {\n                    @Override\n                    public int compare(Size lhs, Size rhs) {\n                        return Long.signum(lhs.getWidth() * lhs.getHeight() - rhs.getHeight() * rhs.getWidth());\n                    }\n                });\n                //此ImageReader用于拍照所需\n                setupImageReader();\n                mCameraId = cameraId;\n                break;\n            }\n        } catch (CameraAccessException e) {\n            e.printStackTrace();\n        }\n    }\n\n    //选择sizeMap中大于并且最接近width和height的size\n    private Size getOptimalSize(Size[] sizeMap, int width, int height) {\n        List<Size> sizeList = new ArrayList<>();\n        for (Size option : sizeMap) {\n            if (width > height) {\n                if (option.getWidth() > width && option.getHeight() > height) {\n                    sizeList.add(option);\n                }\n            } else {\n                if (option.getWidth() > height && option.getHeight() > width) {\n                    sizeList.add(option);\n                }\n            }\n        }\n        if (sizeList.size() > 0) {\n            return Collections.min(sizeList, new Comparator<Size>() {\n                @Override\n                public int compare(Size lhs, Size rhs) {\n                    return Long.signum(lhs.getWidth() * lhs.getHeight() - rhs.getWidth() * rhs.getHeight());\n                }\n            });\n        }\n        return sizeMap[0];\n    }\n\n\n    private void openCamera() {\n        CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);\n        try {\n            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {\n                return;\n            }\n            manager.openCamera(mCameraId, mStateCallback, mCameraHandler);\n        } catch (CameraAccessException e) {\n            e.printStackTrace();\n        }\n    }\n\n    private CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {\n        @Override\n        public void onOpened(CameraDevice camera) {\n            mCameraDevice = camera;\n            startPreview();\n        }\n\n        @Override\n        public void onDisconnected(CameraDevice camera) {\n            camera.close();\n            mCameraDevice = null;\n        }\n\n        @Override\n        public void onError(CameraDevice camera, int error) {\n            camera.close();\n            mCameraDevice = null;\n        }\n    };\n\n    private void startPreview() {\n        SurfaceTexture mSurfaceTexture = mTextureView.getSurfaceTexture();\n        mSurfaceTexture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());\n        Surface previewSurface = new Surface(mSurfaceTexture);\n        try {\n            mCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);\n            mCaptureRequestBuilder.addTarget(previewSurface);\n            mCameraDevice.createCaptureSession(Arrays.asList(previewSurface, mImageReader.getSurface()), new CameraCaptureSession.StateCallback() {\n                @Override\n                public void onConfigured(CameraCaptureSession session) {\n                    try {\n                        mCaptureRequest = mCaptureRequestBuilder.build();\n                        mCameraCaptureSession = session;\n                        mCameraCaptureSession.setRepeatingRequest(mCaptureRequest, null, mCameraHandler);\n                    } catch (CameraAccessException e) {\n                        e.printStackTrace();\n                    }\n                }\n\n                @Override\n                public void onConfigureFailed(CameraCaptureSession session) {\n\n                }\n            }, mCameraHandler);\n        } catch (CameraAccessException e) {\n            e.printStackTrace();\n        }\n    }\n\n    public void takePicture(View view) {\n        lockFocus();\n    }\n\n    private void lockFocus() {\n        try {\n            mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);\n            mCameraCaptureSession.capture(mCaptureRequestBuilder.build(), mCaptureCallback, mCameraHandler);\n        } catch (CameraAccessException e) {\n            e.printStackTrace();\n        }\n    }\n\n    private CameraCaptureSession.CaptureCallback mCaptureCallback = new CameraCaptureSession.CaptureCallback() {\n        @Override\n        public void onCaptureProgressed(CameraCaptureSession session, CaptureRequest request, CaptureResult partialResult) {\n        }\n\n        @Override\n        public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {\n            capture();\n        }\n    };\n\n    private void capture() {\n        try {\n            final CaptureRequest.Builder mCaptureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);\n            int rotation = getWindowManager().getDefaultDisplay().getRotation();\n            mCaptureBuilder.addTarget(mImageReader.getSurface());\n            mCaptureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATION.get(rotation));\n            CameraCaptureSession.CaptureCallback CaptureCallback = new CameraCaptureSession.CaptureCallback() {\n                @Override\n                public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {\n                    Toast.makeText(getApplicationContext(), \"Image Saved!\", Toast.LENGTH_SHORT).show();\n                    unLockFocus();\n                }\n            };\n            mCameraCaptureSession.stopRepeating();\n            mCameraCaptureSession.capture(mCaptureBuilder.build(), CaptureCallback, null);\n        } catch (CameraAccessException e) {\n            e.printStackTrace();\n        }\n    }\n\n    private void unLockFocus() {\n        try {\n            mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);\n            //mCameraCaptureSession.capture(mCaptureRequestBuilder.build(), null, mCameraHandler);\n            mCameraCaptureSession.setRepeatingRequest(mCaptureRequest, null, mCameraHandler);\n        } catch (CameraAccessException e) {\n            e.printStackTrace();\n        }\n    }\n\n    @Override\n    protected void onPause() {\n        super.onPause();\n        if (mCameraCaptureSession != null) {\n            mCameraCaptureSession.close();\n            mCameraCaptureSession = null;\n        }\n\n        if (mCameraDevice != null) {\n            mCameraDevice.close();\n            mCameraDevice = null;\n        }\n\n        if (mImageReader != null) {\n            mImageReader.close();\n            mImageReader = null;\n        }\n    }\n\n    private void setupImageReader() {\n        //2代表ImageReader中最多可以获取两帧图像流\n        mImageReader = ImageReader.newInstance(mCaptureSize.getWidth(), mCaptureSize.getHeight(),\n                ImageFormat.JPEG, 2);\n        mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {\n            @Override\n            public void onImageAvailable(ImageReader reader) {\n                mCameraHandler.post(new imageSaver(reader.acquireNextImage()));\n            }\n        }, mCameraHandler);\n    }\n\n    public static class imageSaver implements Runnable {\n\n        private Image mImage;\n\n        public imageSaver(Image image) {\n            mImage = image;\n        }\n\n        @Override\n        public void run() {\n            ByteBuffer buffer = mImage.getPlanes()[0].getBuffer();\n            byte[] data = new byte[buffer.remaining()];\n            buffer.get(data);\n            String path = Environment.getExternalStorageDirectory() + \"/DCIM/CameraV2/\";\n            File mImageFile = new File(path);\n            if (!mImageFile.exists()) {\n                mImageFile.mkdir();\n            }\n            String timeStamp = new SimpleDateFormat(\"yyyyMMdd_HHmmss\").format(new Date());\n            String fileName = path + \"IMG_\" + timeStamp + \".jpg\";\n            FileOutputStream fos = null;\n            try {\n                fos = new FileOutputStream(fileName);\n                fos.write(data, 0, data.length);\n            } catch (IOException e) {\n                e.printStackTrace();\n            } finally {\n                if (fos != null) {\n                    try {\n                        fos.close();\n                    } catch (IOException e) {\n                        e.printStackTrace();\n                    }\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Camera/CameraV2/app/src/main/res/layout/activity_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:context=\"com.lb377463323.camera2.MainActivity\">\n\n    <TextureView\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:id=\"@+id/textureView\"\n        android:layout_centerHorizontal=\"true\"\n        android:layout_centerVertical=\"true\"/>\n\n    <Button\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"拍照\"\n        android:id=\"@+id/photoButton\"\n        android:onClick=\"takePicture\"\n        android:layout_alignParentBottom=\"true\"\n        android:layout_centerHorizontal=\"true\"/>\n\n</RelativeLayout>\n"
  },
  {
    "path": "Camera/CameraV2/app/src/main/res/layout/gallery_imageview.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"match_parent\">\n    <ImageView\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:id=\"@+id/galleryImageView\"\n        android:layout_margin=\"10dp\"\n        android:layout_alignParentTop=\"true\"/>\n\n</RelativeLayout>"
  },
  {
    "path": "Camera/CameraV2/app/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#3F51B5</color>\n    <color name=\"colorPrimaryDark\">#303F9F</color>\n    <color name=\"colorAccent\">#FF4081</color>\n</resources>\n"
  },
  {
    "path": "Camera/CameraV2/app/src/main/res/values/dimens.xml",
    "content": "<resources>\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"activity_horizontal_margin\">16dp</dimen>\n    <dimen name=\"activity_vertical_margin\">16dp</dimen>\n</resources>\n"
  },
  {
    "path": "Camera/CameraV2/app/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">CameraV2</string>\n</resources>\n"
  },
  {
    "path": "Camera/CameraV2/app/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar\">\n        <!-- Customize your theme here. -->\n        <item name=\"colorPrimary\">@color/colorPrimary</item>\n        <item name=\"colorPrimaryDark\">@color/colorPrimaryDark</item>\n        <item name=\"colorAccent\">@color/colorAccent</item>\n    </style>\n\n</resources>\n"
  },
  {
    "path": "Camera/CameraV2/app/src/main/res/values-w820dp/dimens.xml",
    "content": "<resources>\n    <!-- Example customization of dimensions originally defined in res/values/dimens.xml\n         (such as screen margins) for screens with more than 820dp of available width. This\n         would include 7\" and 10\" devices in landscape (~960dp and ~1280dp respectively). -->\n    <dimen name=\"activity_horizontal_margin\">64dp</dimen>\n</resources>\n"
  },
  {
    "path": "Camera/CameraV2/build.gradle",
    "content": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n    repositories {\n        jcenter()\n    }\n    dependencies {\n        classpath 'com.android.tools.build:gradle:2.3.0'\n\n        // NOTE: Do not place your application dependencies here; they belong\n        // in the individual module build.gradle files\n    }\n}\n\nallprojects {\n    repositories {\n        jcenter()\n    }\n}\n\ntask clean(type: Delete) {\n    delete rootProject.buildDir\n}\n"
  },
  {
    "path": "Camera/CameraV2/gradle/wrapper/gradle-wrapper.properties",
    "content": "#Wed Oct 21 11:34:03 PDT 2015\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-3.5-all.zip\n"
  },
  {
    "path": "Camera/CameraV2/gradle.properties",
    "content": "# Project-wide Gradle settings.\n\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will override*\n# any settings specified in this file.\n\n# For more details on how to configure your build environment visit\n# http://www.gradle.org/docs/current/userguide/build_environment.html\n\n# Specifies the JVM arguments used for the daemon process.\n# The setting is particularly useful for tweaking memory settings.\n# Default value: -Xmx10248m -XX:MaxPermSize=256m\n# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8\n\n# When configured, Gradle will run in incubating parallel mode.\n# This option should only be used with decoupled projects. More details, visit\n# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects\n# org.gradle.parallel=true"
  },
  {
    "path": "Camera/CameraV2/gradlew",
    "content": "#!/usr/bin/env bash\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS=\"\"\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn ( ) {\n    echo \"$*\"\n}\n\ndie ( ) {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\nesac\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done\n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules\nfunction splitJvmOpts() {\n    JVM_OPTS=(\"$@\")\n}\neval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\nJVM_OPTS[${#JVM_OPTS[*]}]=\"-Dorg.gradle.appname=$APP_BASE_NAME\"\n\nexec \"$JAVACMD\" \"${JVM_OPTS[@]}\" -classpath \"$CLASSPATH\" org.gradle.wrapper.GradleWrapperMain \"$@\"\n"
  },
  {
    "path": "Camera/CameraV2/gradlew.bat",
    "content": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem  Gradle startup script for Windows\n@rem\n@rem ##########################################################################\n\n@rem Set local scope for the variables with windows NT shell\nif \"%OS%\"==\"Windows_NT\" setlocal\n\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nset DEFAULT_JVM_OPTS=\n\nset DIRNAME=%~dp0\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\nset APP_BASE_NAME=%~n0\nset APP_HOME=%DIRNAME%\n\n@rem Find java.exe\nif defined JAVA_HOME goto findJavaFromJavaHome\n\nset JAVA_EXE=java.exe\n%JAVA_EXE% -version >NUL 2>&1\nif \"%ERRORLEVEL%\" == \"0\" goto init\n\necho.\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:findJavaFromJavaHome\nset JAVA_HOME=%JAVA_HOME:\"=%\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\n\nif exist \"%JAVA_EXE%\" goto init\n\necho.\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:init\n@rem Get command-line arguments, handling Windowz variants\n\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\nif \"%@eval[2+2]\" == \"4\" goto 4NT_args\n\n:win9xME_args\n@rem Slurp the command line arguments.\nset CMD_LINE_ARGS=\nset _SKIP=2\n\n:win9xME_args_slurp\nif \"x%~1\" == \"x\" goto execute\n\nset CMD_LINE_ARGS=%*\ngoto execute\n\n:4NT_args\n@rem Get arguments from the 4NT Shell from JP Software\nset CMD_LINE_ARGS=%$\n\n:execute\n@rem Setup the command line\n\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\n\n@rem Execute Gradle\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\n\n:end\n@rem End local scope for the variables with windows NT shell\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\n\n:fail\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\nrem the _cmd.exe /c_ return code!\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\nexit /b 1\n\n:mainEnd\nif \"%OS%\"==\"Windows_NT\" endlocal\n\n:omega\n"
  },
  {
    "path": "Camera/CameraV2/settings.gradle",
    "content": "include ':app'\n"
  },
  {
    "path": "Filter/.gitignore",
    "content": "*.iml\n.gradle\n/local.properties\n/.idea/workspace.xml\n/.idea/libraries\n.DS_Store\n/build\n/captures\n"
  },
  {
    "path": "Filter/.idea/gradle.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"GradleSettings\">\n    <option name=\"linkedExternalProjectsSettings\">\n      <GradleProjectSettings>\n        <option name=\"distributionType\" value=\"DEFAULT_WRAPPED\" />\n        <option name=\"externalProjectPath\" value=\"$PROJECT_DIR$\" />\n        <option name=\"modules\">\n          <set>\n            <option value=\"$PROJECT_DIR$\" />\n            <option value=\"$PROJECT_DIR$/app\" />\n          </set>\n        </option>\n        <option name=\"resolveModulePerSourceSet\" value=\"false\" />\n      </GradleProjectSettings>\n    </option>\n  </component>\n</project>"
  },
  {
    "path": "Filter/.idea/misc.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"NullableNotNullManager\">\n    <option name=\"myDefaultNullable\" value=\"android.support.annotation.Nullable\" />\n    <option name=\"myDefaultNotNull\" value=\"android.support.annotation.NonNull\" />\n    <option name=\"myNullables\">\n      <value>\n        <list size=\"4\">\n          <item index=\"0\" class=\"java.lang.String\" itemvalue=\"org.jetbrains.annotations.Nullable\" />\n          <item index=\"1\" class=\"java.lang.String\" itemvalue=\"javax.annotation.Nullable\" />\n          <item index=\"2\" class=\"java.lang.String\" itemvalue=\"edu.umd.cs.findbugs.annotations.Nullable\" />\n          <item index=\"3\" class=\"java.lang.String\" itemvalue=\"android.support.annotation.Nullable\" />\n        </list>\n      </value>\n    </option>\n    <option name=\"myNotNulls\">\n      <value>\n        <list size=\"4\">\n          <item index=\"0\" class=\"java.lang.String\" itemvalue=\"org.jetbrains.annotations.NotNull\" />\n          <item index=\"1\" class=\"java.lang.String\" itemvalue=\"javax.annotation.Nonnull\" />\n          <item index=\"2\" class=\"java.lang.String\" itemvalue=\"edu.umd.cs.findbugs.annotations.NonNull\" />\n          <item index=\"3\" class=\"java.lang.String\" itemvalue=\"android.support.annotation.NonNull\" />\n        </list>\n      </value>\n    </option>\n  </component>\n  <component name=\"ProjectRootManager\" version=\"2\" languageLevel=\"JDK_1_7\" project-jdk-name=\"1.8\" project-jdk-type=\"JavaSDK\">\n    <output url=\"file://$PROJECT_DIR$/build/classes\" />\n  </component>\n  <component name=\"ProjectType\">\n    <option name=\"id\" value=\"Android\" />\n  </component>\n</project>"
  },
  {
    "path": "Filter/.idea/modules.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"ProjectModuleManager\">\n    <modules>\n      <module fileurl=\"file://$PROJECT_DIR$/Filter.iml\" filepath=\"$PROJECT_DIR$/Filter.iml\" />\n      <module fileurl=\"file://$PROJECT_DIR$/app/app.iml\" filepath=\"$PROJECT_DIR$/app/app.iml\" />\n    </modules>\n  </component>\n</project>"
  },
  {
    "path": "Filter/.idea/runConfigurations.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"RunConfigurationProducerService\">\n    <option name=\"ignoredProducers\">\n      <set>\n        <option value=\"org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer\" />\n        <option value=\"org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer\" />\n        <option value=\"org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer\" />\n      </set>\n    </option>\n  </component>\n</project>"
  },
  {
    "path": "Filter/app/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "Filter/app/build.gradle",
    "content": "apply plugin: 'com.android.application'\n\nandroid {\n    compileSdkVersion 25\n    buildToolsVersion \"25.0.2\"\n\n    defaultConfig {\n        applicationId \"com.liubing.filtertestbed\"\n        minSdkVersion 21\n        targetSdkVersion 25\n        versionCode 1\n        versionName \"1.0\"\n    }\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n        }\n    }\n}\n\ndependencies {\n    compile fileTree(include: ['*.jar'], dir: 'libs')\n    compile 'com.android.support:appcompat-v7:25.3.1'\n}\n"
  },
  {
    "path": "Filter/app/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in E:\\AndroidSdk/tools/proguard/proguard-android.txt\n# You can edit the include path and order by changing the proguardFiles\n# directive in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# Add any project specific keep options here:\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n"
  },
  {
    "path": "Filter/app/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest package=\"com.liubing.filtertestbed\"\n          xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <uses-permission android:name=\"android.permission.CAMERA\"/>\n\n    <uses-feature android:name=\"android.hardware.camera\"/>\n    <uses-feature android:name=\"android.hardware.camera.autofocus\"/>\n    <uses-feature android:name=\"android.hardware.camera2.full\" />\n\n    <application\n        android:allowBackup=\"true\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:supportsRtl=\"true\"\n        android:theme=\"@style/AppTheme\">\n        <!--<activity android:name=\".CameraV1GLSurfaceView.CameraV1GLSurfaceViewActivity\"\n                  android:configChanges=\"orientation|keyboardHidden|screenSize\"\n                  android:screenOrientation=\"portrait\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\"/>\n\n                <category android:name=\"android.intent.category.LAUNCHER\"/>\n            </intent-filter>\n        </activity>-->\n\n        <!--<activity android:name=\".CameraV1TextureView.CameraV1TextureViewActivity\"\n                  android:configChanges=\"orientation|keyboardHidden|screenSize\"\n                  android:screenOrientation=\"portrait\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\"/>\n\n                <category android:name=\"android.intent.category.LAUNCHER\"/>\n            </intent-filter>\n        </activity>-->\n\n        <activity android:name=\".CameraV2GLSurfaceView.CameraV2GLSurfaceViewActivity\"\n                  android:configChanges=\"orientation|keyboardHidden|screenSize\"\n                  android:screenOrientation=\"portrait\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\"/>\n\n                <category android:name=\"android.intent.category.LAUNCHER\"/>\n            </intent-filter>\n        </activity>\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "Filter/app/src/main/java/com/liubing/filtertestbed/CameraV1.java",
    "content": "package com.liubing.filtertestbed;\n\nimport android.app.Activity;\nimport android.graphics.SurfaceTexture;\nimport android.hardware.Camera;\nimport android.util.Log;\nimport android.view.Surface;\n\nimport java.io.IOException;\n\n/**\n * Created by lb6905 on 2017/6/27.\n */\n\npublic class CameraV1 {\n    private Activity mActivity;\n    private int mCameraId;\n    private Camera mCamera;\n\n    public CameraV1(Activity activity) {\n        mActivity = activity;\n    }\n\n    public boolean openCamera(int screenWidth, int screenHeight, int cameraId) {\n        try {\n            mCameraId = cameraId;\n            mCamera = Camera.open(mCameraId);\n            Camera.Parameters parameters = mCamera.getParameters();\n            parameters.set(\"orientation\", \"portrait\");\n            parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);\n            parameters.setPreviewSize(1280, 720);\n            setCameraDisplayOrientation(mActivity, mCameraId, mCamera);\n            mCamera.setParameters(parameters);\n            Log.i(\"lb6905\", \"open camera\");\n        } catch (Exception e) {\n            e.printStackTrace();\n            return false;\n        }\n        return true;\n    }\n\n    public static void setCameraDisplayOrientation(Activity activity,\n                                                   int cameraId, android.hardware.Camera camera) {\n        android.hardware.Camera.CameraInfo info =\n                new android.hardware.Camera.CameraInfo();\n        android.hardware.Camera.getCameraInfo(cameraId, info);\n        int rotation = activity.getWindowManager().getDefaultDisplay()\n                .getRotation();\n        int degrees = 0;\n        switch (rotation) {\n            case Surface.ROTATION_0: degrees = 0; break;\n            case Surface.ROTATION_90: degrees = 90; break;\n            case Surface.ROTATION_180: degrees = 180; break;\n            case Surface.ROTATION_270: degrees = 270; break;\n        }\n\n        int result;\n        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {\n            result = (info.orientation + degrees) % 360;\n            result = (360 - result) % 360;  // compensate the mirror\n        } else {  // back-facing\n            result = (info.orientation - degrees + 360) % 360;\n        }\n        camera.setDisplayOrientation(result);\n    }\n\n    public void startPreview() {\n        if (mCamera != null) {\n            mCamera.startPreview();\n        }\n    }\n\n    public void stopPreview() {\n        if (mCamera != null) {\n            mCamera.stopPreview();\n        }\n    }\n\n    public void setPreviewTexture(SurfaceTexture surfaceTexture) {\n        if (mCamera != null) {\n            try {\n                mCamera.setPreviewTexture(surfaceTexture);\n            } catch (IOException e) {\n                e.printStackTrace();\n            }\n        }\n    }\n\n    public void releaseCamera() {\n        if (mCamera != null) {\n            mCamera.release();\n            mCamera = null;\n        }\n    }\n}\n"
  },
  {
    "path": "Filter/app/src/main/java/com/liubing/filtertestbed/CameraV1GLSurfaceView/CameraV1GLSurfaceView.java",
    "content": "package com.liubing.filtertestbed.CameraV1GLSurfaceView;\n\nimport android.content.Context;\nimport android.opengl.GLSurfaceView;\n\nimport com.liubing.filtertestbed.CameraV1;\n\n/**\n * Created by lb6905 on 2017/6/12.\n */\n\npublic class CameraV1GLSurfaceView extends GLSurfaceView {\n\n    private CameraV1Renderer mRenderer;\n    private int textureId = -1;\n\n    public CameraV1GLSurfaceView(Context context) {\n        super(context);\n    }\n\n    public void init(CameraV1 camera, boolean isPreviewStarted, Context context) {\n        setEGLContextClientVersion(2);\n        mRenderer = new CameraV1Renderer();\n        mRenderer.init(this, camera, isPreviewStarted, context);\n        setRenderer(mRenderer);\n    }\n\n    public void deinit() {\n        if (mRenderer != null) {\n            mRenderer.deinit();\n            mRenderer = null;\n            textureId = -1;\n        }\n    }\n}\n"
  },
  {
    "path": "Filter/app/src/main/java/com/liubing/filtertestbed/CameraV1GLSurfaceView/CameraV1GLSurfaceViewActivity.java",
    "content": "package com.liubing.filtertestbed.CameraV1GLSurfaceView;\n\nimport android.app.Activity;\nimport android.content.pm.ActivityInfo;\nimport android.hardware.Camera;\nimport android.os.Bundle;\nimport android.util.DisplayMetrics;\nimport android.view.Window;\nimport android.view.WindowManager;\n\nimport com.liubing.filtertestbed.CameraV1;\n\npublic class CameraV1GLSurfaceViewActivity extends Activity {\n    private CameraV1GLSurfaceView mGLSurfaceView;\n    private int mCameraId;\n    private CameraV1 mCamera;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n\n        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);\n        requestWindowFeature(Window.FEATURE_NO_TITLE);\n        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);\n\n        mGLSurfaceView = new CameraV1GLSurfaceView(this);\n        mCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;\n        DisplayMetrics dm = new DisplayMetrics();\n        mCamera = new CameraV1(this);\n        if (!mCamera.openCamera(dm.widthPixels, dm.heightPixels, mCameraId)) {\n            return;\n        }\n        mGLSurfaceView.init(mCamera, false, CameraV1GLSurfaceViewActivity.this);\n        setContentView(mGLSurfaceView);\n    }\n\n    @Override\n    protected void onPause() {\n        super.onPause();\n        if (mGLSurfaceView != null) {\n            mGLSurfaceView.onPause();\n            mGLSurfaceView.deinit();\n            mGLSurfaceView = null;\n        }\n\n        if (mCamera != null) {\n            mCamera.stopPreview();\n            mCamera.releaseCamera();\n            mCamera = null;\n        }\n    }\n\n    @Override\n    protected void onDestroy() {\n        super.onDestroy();\n    }\n}\n"
  },
  {
    "path": "Filter/app/src/main/java/com/liubing/filtertestbed/CameraV1GLSurfaceView/CameraV1Renderer.java",
    "content": "package com.liubing.filtertestbed.CameraV1GLSurfaceView;\n\nimport android.content.Context;\nimport android.graphics.SurfaceTexture;\nimport android.opengl.GLES11Ext;\nimport android.opengl.GLES20;\nimport android.opengl.GLSurfaceView;\nimport android.util.Log;\n\nimport com.liubing.filtertestbed.FilterEngine;\nimport com.liubing.filtertestbed.CameraV1;\nimport com.liubing.filtertestbed.Utils;\n\nimport java.nio.FloatBuffer;\n\nimport javax.microedition.khronos.egl.EGLConfig;\nimport javax.microedition.khronos.opengles.GL10;\n\nimport static android.opengl.GLES11Ext.GL_TEXTURE_EXTERNAL_OES;\nimport static android.opengl.GLES20.GL_FLOAT;\nimport static android.opengl.GLES20.GL_FRAMEBUFFER;\nimport static android.opengl.GLES20.GL_TRIANGLES;\nimport static android.opengl.GLES20.glActiveTexture;\nimport static android.opengl.GLES20.glBindFramebuffer;\nimport static android.opengl.GLES20.glBindTexture;\nimport static android.opengl.GLES20.glClearColor;\nimport static android.opengl.GLES20.glDrawArrays;\nimport static android.opengl.GLES20.glEnableVertexAttribArray;\nimport static android.opengl.GLES20.glGenFramebuffers;\nimport static android.opengl.GLES20.glGetAttribLocation;\nimport static android.opengl.GLES20.glGetUniformLocation;\nimport static android.opengl.GLES20.glUniform1i;\nimport static android.opengl.GLES20.glUniformMatrix4fv;\nimport static android.opengl.GLES20.glVertexAttribPointer;\nimport static android.opengl.GLES20.glViewport;\n\n/**\n * Created by lb6905 on 2017/6/12.\n */\n\npublic class CameraV1Renderer implements GLSurfaceView.Renderer {\n\n    private static final String TAG = \"Filter_MyRenderer\";\n    private Context mContext;\n    private int mOESTextureId = -1;\n    private SurfaceTexture mSurfaceTexture;\n    private float[] transformMatrix = new float[16];\n    private CameraV1GLSurfaceView mGLSurfaceView;\n    private CameraV1 mCamera;\n    private boolean bIsPreviewStarted;\n    private FilterEngine mFilterEngine;\n    private FloatBuffer mDataBuffer;\n    private int mShaderProgram = -1;\n    private int aPositionLocation = -1;\n    private int aTextureCoordLocation = -1;\n    private int uTextureMatrixLocation = -1;\n    private int uTextureSamplerLocation = -1;\n    private int[] mFBOIds = new int[1];\n\n    public void init(CameraV1GLSurfaceView glSurfaceView, CameraV1 camera, boolean isPreviewStarted, Context context) {\n        mContext = context;\n        mGLSurfaceView = glSurfaceView;\n        mCamera = camera;\n        bIsPreviewStarted = isPreviewStarted;\n    }\n\n    @Override\n    public void onSurfaceCreated(GL10 gl, EGLConfig config) {\n        mOESTextureId = Utils.createOESTextureObject();\n        mFilterEngine = new FilterEngine(mOESTextureId, mContext);\n        mDataBuffer = mFilterEngine.getBuffer();\n        mShaderProgram = mFilterEngine.getShaderProgram();\n        glGenFramebuffers(1, mFBOIds, 0);\n        glBindFramebuffer(GL_FRAMEBUFFER, mFBOIds[0]);\n        Log.i(\"lb6905\", \"onSurfaceCreated: mFBOId: \" + mFBOIds[0]);\n    }\n\n    @Override\n    public void onSurfaceChanged(GL10 gl, int width, int height) {\n        glViewport(0, 0, width, height);\n    }\n\n    @Override\n    public void onDrawFrame(GL10 gl) {\n        Long t1 = System.currentTimeMillis();\n        if (mSurfaceTexture != null) {\n            mSurfaceTexture.updateTexImage();\n            mSurfaceTexture.getTransformMatrix(transformMatrix);\n        }\n\n        if (!bIsPreviewStarted) {\n            bIsPreviewStarted = initSurfaceTexture();\n            bIsPreviewStarted = true;\n            return;\n        }\n\n        //glClear(GL_COLOR_BUFFER_BIT);\n        glClearColor(1.0f, 0.0f, 0.0f, 0.0f);\n\n        aPositionLocation = glGetAttribLocation(mShaderProgram, FilterEngine.POSITION_ATTRIBUTE);\n        aTextureCoordLocation = glGetAttribLocation(mShaderProgram, FilterEngine.TEXTURE_COORD_ATTRIBUTE);\n        uTextureMatrixLocation = glGetUniformLocation(mShaderProgram, FilterEngine.TEXTURE_MATRIX_UNIFORM);\n        uTextureSamplerLocation = glGetUniformLocation(mShaderProgram, FilterEngine.TEXTURE_SAMPLER_UNIFORM);\n\n        glActiveTexture(GLES20.GL_TEXTURE0);\n        glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mOESTextureId);\n        glUniform1i(uTextureSamplerLocation, 0);\n        glUniformMatrix4fv(uTextureMatrixLocation, 1, false, transformMatrix, 0);\n\n        if (mDataBuffer != null) {\n            mDataBuffer.position(0);\n            glEnableVertexAttribArray(aPositionLocation);\n            glVertexAttribPointer(aPositionLocation, 2, GL_FLOAT, false, 16, mDataBuffer);\n\n            mDataBuffer.position(2);\n            glEnableVertexAttribArray(aTextureCoordLocation);\n            glVertexAttribPointer(aTextureCoordLocation, 2, GL_FLOAT, false, 16, mDataBuffer);\n        }\n\n        //glDrawElements(GL_TRIANGLE_FAN, 6,GL_UNSIGNED_INT, 0);\n        //glDrawArrays(GL_TRIANGLE_FAN, 0 , 6);\n        glDrawArrays(GL_TRIANGLES, 0, 6);\n        //glDrawArrays(GL_TRIANGLES, 3, 3);\n        glBindFramebuffer(GL_FRAMEBUFFER, 0);\n        long t2 = System.currentTimeMillis();\n        long t = t2 - t1;\n        Log.i(\"lb6905\", \"onDrawFrame: time: \" + t);\n    }\n\n    public boolean initSurfaceTexture() {\n        if (mCamera == null || mGLSurfaceView == null) {\n            Log.i(TAG, \"mCamera or mGLSurfaceView is null!\");\n            return false;\n        }\n        mSurfaceTexture = new SurfaceTexture(mOESTextureId);\n        mSurfaceTexture.setOnFrameAvailableListener(new SurfaceTexture.OnFrameAvailableListener() {\n            @Override\n            public void onFrameAvailable(SurfaceTexture surfaceTexture) {\n                mGLSurfaceView.requestRender();\n            }\n        });\n        mCamera.setPreviewTexture(mSurfaceTexture);\n        mCamera.startPreview();\n        return true;\n    }\n\n    public void deinit() {\n        if (mFilterEngine != null) {\n            mFilterEngine = null;\n        }\n        mDataBuffer = null;\n        if (mSurfaceTexture != null) {\n            mSurfaceTexture.release();\n            mSurfaceTexture = null;\n        }\n        mCamera = null;\n        mOESTextureId = -1;\n        bIsPreviewStarted = false;\n    }\n}\n"
  },
  {
    "path": "Filter/app/src/main/java/com/liubing/filtertestbed/CameraV1TextureView/CameraV1GLRenderer.java",
    "content": "package com.liubing.filtertestbed.CameraV1TextureView;\n\nimport android.content.Context;\nimport android.graphics.SurfaceTexture;\nimport android.opengl.EGL14;\nimport android.opengl.GLES20;\nimport android.os.Handler;\nimport android.os.HandlerThread;\nimport android.os.Message;\nimport android.util.Log;\nimport android.view.TextureView;\n\nimport com.liubing.filtertestbed.FilterEngine;\n\nimport java.nio.FloatBuffer;\n\nimport javax.microedition.khronos.egl.EGL10;\nimport javax.microedition.khronos.egl.EGLConfig;\nimport javax.microedition.khronos.egl.EGLContext;\nimport javax.microedition.khronos.egl.EGLDisplay;\nimport javax.microedition.khronos.egl.EGLSurface;\n\n/**\n * Created by lb6905 on 2017/6/28.\n */\n\npublic class CameraV1GLRenderer implements SurfaceTexture.OnFrameAvailableListener {\n    private static final String TAG = \"Filter_GLRenderer\";\n    private Context mContext;\n    private HandlerThread mHandlerThread;\n    private Handler mHandler;\n    private TextureView mTextureView;\n    private int mOESTextureId;\n    private FilterEngine mFilterEngine;\n    private FloatBuffer mDataBuffer;\n    private int mShaderProgram = -1;\n    private float[] transformMatrix = new float[16];\n\n    private EGL10 mEgl = null;\n    private EGLDisplay mEGLDisplay = EGL10.EGL_NO_DISPLAY;\n    private EGLContext mEGLContext = EGL10.EGL_NO_CONTEXT;\n    private EGLConfig[] mEGLConfig = new EGLConfig[1];\n    private EGLSurface mEglSurface;\n\n    private static final int MSG_INIT = 1;\n    private static final int MSG_RENDER = 2;\n    private static final int MSG_DEINIT = 3;\n    private SurfaceTexture mOESSurfaceTexture;\n\n    public void init(TextureView textureView, int oesTextureId, Context context) {\n        mContext = context;\n        mTextureView = textureView;\n        mOESTextureId = oesTextureId;\n        mHandlerThread = new HandlerThread(\"Renderer Thread\");\n        mHandlerThread.start();\n        mHandler = new Handler(mHandlerThread.getLooper()){\n            @Override\n            public void handleMessage(Message msg) {\n                switch (msg.what) {\n                    case MSG_INIT:\n                        initEGL();\n                        return;\n                    case MSG_RENDER:\n                        drawFrame();\n                        return;\n                    case MSG_DEINIT:\n                        return;\n                    default:\n                        return;\n                }\n            }\n        };\n        mHandler.sendEmptyMessage(MSG_INIT);\n    }\n\n    private void initEGL() {\n        mEgl = (EGL10) EGLContext.getEGL();\n\n        //获取显示设备\n        mEGLDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);\n        if (mEGLDisplay == EGL10.EGL_NO_DISPLAY) {\n            throw new RuntimeException(\"eglGetDisplay failed! \" + mEgl.eglGetError());\n        }\n\n        //version中存放EGL版本号\n        int[] version = new int[2];\n\n        //初始化EGL\n        if (!mEgl.eglInitialize(mEGLDisplay, version)) {\n            throw new RuntimeException(\"eglInitialize failed! \" + mEgl.eglGetError());\n        }\n\n        //构造需要的配置列表\n        int[] attributes = {\n                EGL10.EGL_RED_SIZE, 8,\n                EGL10.EGL_GREEN_SIZE,8,\n                EGL10.EGL_BLUE_SIZE, 8,\n                EGL10.EGL_ALPHA_SIZE, 8,\n                EGL10.EGL_BUFFER_SIZE, 32,\n                EGL10.EGL_RENDERABLE_TYPE, 4,\n                EGL10.EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT,\n                EGL10.EGL_NONE\n        };\n        int[] configsNum = new int[1];\n\n        //EGL选择配置\n        if (!mEgl.eglChooseConfig(mEGLDisplay, attributes, mEGLConfig, 1, configsNum)) {\n            throw new RuntimeException(\"eglChooseConfig failed! \" + mEgl.eglGetError());\n        }\n        SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture();\n        if (surfaceTexture == null)\n            return;\n\n        //创建EGL显示窗口\n        mEglSurface = mEgl.eglCreateWindowSurface(mEGLDisplay, mEGLConfig[0], surfaceTexture, null);\n\n        //创建上下文\n        int[] contextAttribs = {\n                EGL14.EGL_CONTEXT_CLIENT_VERSION, 2,\n                EGL10.EGL_NONE\n        };\n        mEGLContext = mEgl.eglCreateContext(mEGLDisplay, mEGLConfig[0], EGL10.EGL_NO_CONTEXT, contextAttribs);\n\n        if (mEGLDisplay == EGL10.EGL_NO_DISPLAY || mEGLContext == EGL10.EGL_NO_CONTEXT){\n            throw new RuntimeException(\"eglCreateContext fail failed! \" + mEgl.eglGetError());\n        }\n\n        if (!mEgl.eglMakeCurrent(mEGLDisplay,mEglSurface, mEglSurface, mEGLContext)) {\n            throw new RuntimeException(\"eglMakeCurrent failed! \" + mEgl.eglGetError());\n        }\n\n        mFilterEngine = new FilterEngine(mOESTextureId, mContext);\n        mDataBuffer = mFilterEngine.getBuffer();\n        mShaderProgram = mFilterEngine.getShaderProgram();\n    }\n\n    private void drawFrame() {\n        long t1, t2;\n        t1 = System.currentTimeMillis();\n        if (mOESSurfaceTexture != null) {\n            mOESSurfaceTexture.updateTexImage();\n            mOESSurfaceTexture.getTransformMatrix(transformMatrix);\n        }\n        mEgl.eglMakeCurrent(mEGLDisplay, mEglSurface, mEglSurface, mEGLContext);\n        GLES20.glViewport(0,0,mTextureView.getWidth(),mTextureView.getHeight());\n        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);\n        GLES20.glClearColor(1f, 1f, 0f, 0f);\n        mFilterEngine.drawTexture(transformMatrix);\n        mEgl.eglSwapBuffers(mEGLDisplay, mEglSurface);\n        t2 = System.currentTimeMillis();\n        Log.i(TAG, \"drawFrame: time = \" + (t2 - t1));\n    }\n\n    @Override\n    public void onFrameAvailable(SurfaceTexture surfaceTexture) {\n        if (mHandler != null) {\n            mHandler.sendEmptyMessage(MSG_RENDER);\n        }\n    }\n\n    public SurfaceTexture initOESTexture() {\n        mOESSurfaceTexture = new SurfaceTexture(mOESTextureId);\n        mOESSurfaceTexture.setOnFrameAvailableListener(this);\n        return mOESSurfaceTexture;\n    }\n}\n"
  },
  {
    "path": "Filter/app/src/main/java/com/liubing/filtertestbed/CameraV1TextureView/CameraV1TextureViewActivity.java",
    "content": "package com.liubing.filtertestbed.CameraV1TextureView;\n\nimport android.app.Activity;\nimport android.content.pm.ActivityInfo;\nimport android.graphics.SurfaceTexture;\nimport android.hardware.Camera;\nimport android.os.Bundle;\nimport android.support.annotation.Nullable;\nimport android.util.DisplayMetrics;\nimport android.view.TextureView;\nimport android.view.Window;\nimport android.view.WindowManager;\n\nimport com.liubing.filtertestbed.CameraV1;\nimport com.liubing.filtertestbed.Utils;\n\n/**\n * Created by lb6905 on 2017/6/28.\n */\n\npublic class CameraV1TextureViewActivity extends Activity {\n    private static final String TAG = \"Filter_TVActivity\";\n    private TextureView mTextureView;\n    private int mCameraId;\n    private CameraV1 mCamera;\n    private SurfaceTexture mOESSurfaceTexture;\n    private int mOESTextureId = -1;\n    private CameraV1GLRenderer mRenderer;\n\n    @Override\n    protected void onCreate(@Nullable Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n\n        //设置全屏无状态栏，并竖屏显示\n        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);\n        requestWindowFeature(Window.FEATURE_NO_TITLE);\n        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);\n\n        mTextureView = new TextureView(this);\n        mTextureView.setSurfaceTextureListener(mTextureListener);\n        //设置隐藏虚拟按键\n        //mTextureView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);\n        mRenderer = new CameraV1GLRenderer();\n        setContentView(mTextureView);\n    }\n\n    public TextureView.SurfaceTextureListener mTextureListener = new TextureView.SurfaceTextureListener() {\n        @Override\n        public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {\n            mOESTextureId = Utils.createOESTextureObject();\n            mRenderer.init(mTextureView, mOESTextureId, CameraV1TextureViewActivity.this);\n            mOESSurfaceTexture = mRenderer.initOESTexture();\n\n            mCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;\n            DisplayMetrics dm = new DisplayMetrics();\n            mCamera = new CameraV1(CameraV1TextureViewActivity.this);\n            if (!mCamera.openCamera(dm.widthPixels, dm.heightPixels, mCameraId)) {\n                return;\n            }\n\n            mCamera.setPreviewTexture(mOESSurfaceTexture);\n            mCamera.startPreview();\n        }\n\n        @Override\n        public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {\n        }\n\n        @Override\n        public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {\n            if (mCamera != null) {\n                mCamera.stopPreview();\n                mCamera.releaseCamera();\n                mCamera = null;\n            }\n            return true;\n        }\n\n        @Override\n        public void onSurfaceTextureUpdated(SurfaceTexture surface) {\n        }\n    };\n\n    @Override\n    protected void onPause() {\n        super.onPause();\n        if (mCamera != null) {\n            mCamera.stopPreview();\n            mCamera.releaseCamera();\n            mCamera = null;\n        }\n    }\n}\n"
  },
  {
    "path": "Filter/app/src/main/java/com/liubing/filtertestbed/CameraV2.java",
    "content": "package com.liubing.filtertestbed;\n\nimport android.Manifest;\nimport android.app.Activity;\nimport android.content.Context;\nimport android.content.pm.PackageManager;\nimport android.graphics.SurfaceTexture;\nimport android.hardware.camera2.CameraAccessException;\nimport android.hardware.camera2.CameraCaptureSession;\nimport android.hardware.camera2.CameraCharacteristics;\nimport android.hardware.camera2.CameraDevice;\nimport android.hardware.camera2.CameraManager;\nimport android.hardware.camera2.CaptureRequest;\nimport android.hardware.camera2.params.StreamConfigurationMap;\nimport android.os.Handler;\nimport android.os.HandlerThread;\nimport android.support.annotation.NonNull;\nimport android.support.v4.app.ActivityCompat;\nimport android.util.Log;\nimport android.util.Size;\nimport android.view.Surface;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.Comparator;\nimport java.util.List;\n\n/**\n * Created by lb6905 on 2017/7/20.\n */\n\npublic class CameraV2 {\n\n    public static final String TAG = \"Filter_CameraV2\";\n\n    private Activity mActivity;\n    private CameraDevice mCameraDevice;\n    private String mCameraId;\n    private Size mPreviewSize;\n    private HandlerThread mCameraThread;\n    private Handler mCameraHandler;\n    private SurfaceTexture mSurfaceTexture;\n    private CaptureRequest.Builder mCaptureRequestBuilder;\n    private CaptureRequest mCaptureRequest;\n    private CameraCaptureSession mCameraCaptureSession;\n\n    public CameraV2(Activity activity) {\n        mActivity = activity;\n        startCameraThread();\n    }\n\n    public String setupCamera(int width, int height) {\n        CameraManager cameraManager = (CameraManager) mActivity.getSystemService(Context.CAMERA_SERVICE);\n        try {\n            for (String id : cameraManager.getCameraIdList()) {\n                CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(id);\n                if (characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT) {\n                    continue;\n                }\n                StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);\n                mPreviewSize = getOptimalSize(map.getOutputSizes(SurfaceTexture.class), width, height);\n                mCameraId = id;\n                Log.i(TAG, \"preview width = \" + mPreviewSize.getWidth() + \", height = \" + mPreviewSize.getHeight() + \", cameraId = \" + mCameraId);\n            }\n        } catch (CameraAccessException e) {\n            e.printStackTrace();\n        }\n        return mCameraId;\n    }\n\n    public void startCameraThread() {\n        mCameraThread = new HandlerThread(\"CameraThread\");\n        mCameraThread.start();\n        mCameraHandler = new Handler(mCameraThread.getLooper());\n    }\n\n    public boolean openCamera() {\n        CameraManager cameraManager = (CameraManager) mActivity.getSystemService(Context.CAMERA_SERVICE);\n        try {\n            if (ActivityCompat.checkSelfPermission(mActivity, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {\n                return false;\n            }\n            cameraManager.openCamera(mCameraId, mStateCallback, mCameraHandler);\n        } catch (CameraAccessException e) {\n            e.printStackTrace();\n            return false;\n        }\n        return true;\n    }\n\n    public CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {\n        @Override\n        public void onOpened(@NonNull CameraDevice camera) {\n            mCameraDevice = camera;\n        }\n\n        @Override\n        public void onDisconnected(@NonNull CameraDevice camera) {\n            camera.close();\n            mCameraDevice = null;\n        }\n\n        @Override\n        public void onError(@NonNull CameraDevice camera, int error) {\n            camera.close();\n            mCameraDevice = null;\n        }\n    };\n\n    private Size getOptimalSize(Size[] sizeMap, int width, int height) {\n        List<Size> sizeList = new ArrayList<>();\n        for (Size option : sizeMap) {\n            if (width > height) {\n                if (option.getWidth() > width && option.getHeight() > height) {\n                    sizeList.add(option);\n                }\n            } else {\n                if (option.getWidth() > height && option.getHeight() > width) {\n                    sizeList.add(option);\n                }\n            }\n        }\n        if (sizeList.size() > 0) {\n            return Collections.min(sizeList, new Comparator<Size>() {\n                @Override\n                public int compare(Size lhs, Size rhs) {\n                    return Long.signum(lhs.getWidth() * lhs.getHeight() - rhs.getWidth() * rhs.getHeight());\n                }\n            });\n        }\n        return sizeMap[0];\n    }\n\n    public void setPreviewTexture(SurfaceTexture surfaceTexture) {\n        mSurfaceTexture = surfaceTexture;\n    }\n\n    public void startPreview() {\n        mSurfaceTexture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());\n        Surface surface = new Surface(mSurfaceTexture);\n        try {\n            mCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);\n            mCaptureRequestBuilder.addTarget(surface);\n            mCameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback() {\n                @Override\n                public void onConfigured(@NonNull CameraCaptureSession session) {\n                    try {\n                        mCaptureRequest = mCaptureRequestBuilder.build();\n                        mCameraCaptureSession = session;\n                        mCameraCaptureSession.setRepeatingRequest(mCaptureRequest, null, mCameraHandler);\n                    } catch (CameraAccessException e) {\n                        e.printStackTrace();\n                    }\n                }\n\n                @Override\n                public void onConfigureFailed(@NonNull CameraCaptureSession session) {\n\n                }\n            }, mCameraHandler);\n        } catch (CameraAccessException e) {\n            e.printStackTrace();\n        }\n    }\n}\n"
  },
  {
    "path": "Filter/app/src/main/java/com/liubing/filtertestbed/CameraV2GLSurfaceView/CameraV2GLSurfaceView.java",
    "content": "package com.liubing.filtertestbed.CameraV2GLSurfaceView;\n\nimport android.content.Context;\nimport android.opengl.GLSurfaceView;\n\nimport com.liubing.filtertestbed.CameraV1;\nimport com.liubing.filtertestbed.CameraV2;\n\n/**\n * Created by lb6905 on 2017/7/19.\n */\n\npublic class CameraV2GLSurfaceView extends GLSurfaceView {\n    public static final String TAG = \"Filter_CameraV2GLSurfaceView\";\n    private CameraV2Renderer mCameraV2Renderer;\n\n    public void init(CameraV2 camera, boolean isPreviewStarted, Context context) {\n        setEGLContextClientVersion(2);\n\n        mCameraV2Renderer = new CameraV2Renderer();\n        mCameraV2Renderer.init(this, camera, isPreviewStarted, context);\n\n        setRenderer(mCameraV2Renderer);\n    }\n\n    public CameraV2GLSurfaceView(Context context) {\n        super(context);\n    }\n}\n"
  },
  {
    "path": "Filter/app/src/main/java/com/liubing/filtertestbed/CameraV2GLSurfaceView/CameraV2GLSurfaceViewActivity.java",
    "content": "package com.liubing.filtertestbed.CameraV2GLSurfaceView;\n\nimport android.app.Activity;\nimport android.os.Bundle;\nimport android.support.annotation.Nullable;\nimport android.util.DisplayMetrics;\n\nimport com.liubing.filtertestbed.CameraV2;\n\n/**\n * Created by lb6905 on 2017/7/19.\n */\n\npublic class CameraV2GLSurfaceViewActivity extends Activity {\n    private CameraV2GLSurfaceView mCameraV2GLSurfaceView;\n    private CameraV2 mCamera;\n\n    @Override\n    protected void onCreate(@Nullable Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n\n        mCameraV2GLSurfaceView = new CameraV2GLSurfaceView(this);\n        DisplayMetrics dm = new DisplayMetrics();\n        getWindowManager().getDefaultDisplay().getMetrics(dm);\n        mCamera = new CameraV2(this);\n        mCamera.setupCamera(dm.widthPixels, dm.heightPixels);\n        if (!mCamera.openCamera()) {\n            return;\n        }\n        mCameraV2GLSurfaceView.init(mCamera, false, CameraV2GLSurfaceViewActivity.this);\n        setContentView(mCameraV2GLSurfaceView);\n    }\n\n    @Override\n    protected void onResume() {\n        super.onResume();\n    }\n\n    @Override\n    protected void onDestroy() {\n        super.onDestroy();\n    }\n}\n"
  },
  {
    "path": "Filter/app/src/main/java/com/liubing/filtertestbed/CameraV2GLSurfaceView/CameraV2Renderer.java",
    "content": "package com.liubing.filtertestbed.CameraV2GLSurfaceView;\n\nimport android.content.Context;\nimport android.graphics.SurfaceTexture;\nimport android.opengl.GLES11Ext;\nimport android.opengl.GLSurfaceView;\nimport android.util.Log;\n\nimport com.liubing.filtertestbed.CameraV2;\nimport com.liubing.filtertestbed.FilterEngine;\nimport com.liubing.filtertestbed.Utils;\n\nimport java.nio.FloatBuffer;\n\nimport javax.microedition.khronos.egl.EGLConfig;\nimport javax.microedition.khronos.opengles.GL10;\n\nimport static android.opengl.GLES11Ext.GL_TEXTURE_EXTERNAL_OES;\nimport static android.opengl.GLES20.GL_FLOAT;\nimport static android.opengl.GLES20.GL_FRAMEBUFFER;\nimport static android.opengl.GLES20.GL_TRIANGLES;\nimport static android.opengl.GLES20.glActiveTexture;\nimport static android.opengl.GLES20.glBindFramebuffer;\nimport static android.opengl.GLES20.glBindTexture;\nimport static android.opengl.GLES20.glClearColor;\nimport static android.opengl.GLES20.glDrawArrays;\nimport static android.opengl.GLES20.glEnableVertexAttribArray;\nimport static android.opengl.GLES20.glGenFramebuffers;\nimport static android.opengl.GLES20.glGetAttribLocation;\nimport static android.opengl.GLES20.glGetUniformLocation;\nimport static android.opengl.GLES20.glUniform1i;\nimport static android.opengl.GLES20.glUniformMatrix4fv;\nimport static android.opengl.GLES20.glVertexAttribPointer;\nimport static android.opengl.GLES20.glViewport;\n\n/**\n * Created by lb6905 on 2017/7/19.\n */\n\npublic class CameraV2Renderer implements GLSurfaceView.Renderer {\n\n    public static final String TAG = \"Filter_CameraV2Renderer\";\n    private Context mContext;\n    CameraV2GLSurfaceView mCameraV2GLSurfaceView;\n    CameraV2 mCamera;\n    boolean bIsPreviewStarted;\n    private int mOESTextureId = -1;\n    private SurfaceTexture mSurfaceTexture;\n    private float[] transformMatrix = new float[16];\n    private FilterEngine mFilterEngine;\n    private FloatBuffer mDataBuffer;\n    private int mShaderProgram = -1;\n    private int aPositionLocation = -1;\n    private int aTextureCoordLocation = -1;\n    private int uTextureMatrixLocation = -1;\n    private int uTextureSamplerLocation = -1;\n    private int[] mFBOIds = new int[1];\n\n    public void init(CameraV2GLSurfaceView surfaceView, CameraV2 camera, boolean isPreviewStarted, Context context) {\n        mContext = context;\n        mCameraV2GLSurfaceView = surfaceView;\n        mCamera = camera;\n        bIsPreviewStarted = isPreviewStarted;\n    }\n\n    @Override\n    public void onSurfaceCreated(GL10 gl, EGLConfig config) {\n        mOESTextureId = Utils.createOESTextureObject();\n        mFilterEngine = new FilterEngine(mOESTextureId, mContext);\n        mDataBuffer = mFilterEngine.getBuffer();\n        mShaderProgram = mFilterEngine.getShaderProgram();\n        glGenFramebuffers(1, mFBOIds, 0);\n        glBindFramebuffer(GL_FRAMEBUFFER, mFBOIds[0]);\n        Log.i(TAG, \"onSurfaceCreated: mFBOId: \" + mFBOIds[0]);\n    }\n\n    @Override\n    public void onSurfaceChanged(GL10 gl, int width, int height) {\n        glViewport(0, 0, width, height);\n        Log.i(TAG, \"onSurfaceChanged: \" + width + \", \" + height);\n    }\n\n    @Override\n    public void onDrawFrame(GL10 gl) {\n        Long t1 = System.currentTimeMillis();\n        if (mSurfaceTexture != null) {\n            mSurfaceTexture.updateTexImage();\n            mSurfaceTexture.getTransformMatrix(transformMatrix);\n        }\n\n        if (!bIsPreviewStarted) {\n            bIsPreviewStarted = initSurfaceTexture();\n            bIsPreviewStarted = true;\n            return;\n        }\n\n        //glClear(GL_COLOR_BUFFER_BIT);\n        glClearColor(1.0f, 0.0f, 0.0f, 0.0f);\n\n        aPositionLocation = glGetAttribLocation(mShaderProgram, FilterEngine.POSITION_ATTRIBUTE);\n        aTextureCoordLocation = glGetAttribLocation(mShaderProgram, FilterEngine.TEXTURE_COORD_ATTRIBUTE);\n        uTextureMatrixLocation = glGetUniformLocation(mShaderProgram, FilterEngine.TEXTURE_MATRIX_UNIFORM);\n        uTextureSamplerLocation = glGetUniformLocation(mShaderProgram, FilterEngine.TEXTURE_SAMPLER_UNIFORM);\n\n        glActiveTexture(GL_TEXTURE_EXTERNAL_OES);\n        glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mOESTextureId);\n        glUniform1i(uTextureSamplerLocation, 0);\n        glUniformMatrix4fv(uTextureMatrixLocation, 1, false, transformMatrix, 0);\n\n        if (mDataBuffer != null) {\n            mDataBuffer.position(0);\n            glEnableVertexAttribArray(aPositionLocation);\n            glVertexAttribPointer(aPositionLocation, 2, GL_FLOAT, false, 16, mDataBuffer);\n\n            mDataBuffer.position(2);\n            glEnableVertexAttribArray(aTextureCoordLocation);\n            glVertexAttribPointer(aTextureCoordLocation, 2, GL_FLOAT, false, 16, mDataBuffer);\n        }\n\n        //glDrawElements(GL_TRIANGLE_FAN, 6,GL_UNSIGNED_INT, 0);\n        //glDrawArrays(GL_TRIANGLE_FAN, 0 , 6);\n        glDrawArrays(GL_TRIANGLES, 0, 6);\n        //glDrawArrays(GL_TRIANGLES, 3, 3);\n        glBindFramebuffer(GL_FRAMEBUFFER, 0);\n        long t2 = System.currentTimeMillis();\n        long t = t2 - t1;\n        Log.i(TAG, \"onDrawFrame: time: \" + t);\n    }\n\n    public boolean initSurfaceTexture() {\n        if (mCamera == null || mCameraV2GLSurfaceView == null) {\n            Log.i(TAG, \"mCamera or mGLSurfaceView is null!\");\n            return false;\n        }\n        mSurfaceTexture = new SurfaceTexture(mOESTextureId);\n        mSurfaceTexture.setOnFrameAvailableListener(new SurfaceTexture.OnFrameAvailableListener() {\n            @Override\n            public void onFrameAvailable(SurfaceTexture surfaceTexture) {\n                mCameraV2GLSurfaceView.requestRender();\n            }\n        });\n        mCamera.setPreviewTexture(mSurfaceTexture);\n        mCamera.startPreview();\n        return true;\n    }\n}\n"
  },
  {
    "path": "Filter/app/src/main/java/com/liubing/filtertestbed/FilterEngine.java",
    "content": "package com.liubing.filtertestbed;\n\nimport android.content.Context;\nimport android.opengl.GLES11Ext;\n\nimport java.nio.ByteBuffer;\nimport java.nio.ByteOrder;\nimport java.nio.FloatBuffer;\n\nimport static android.opengl.GLES11Ext.GL_TEXTURE_EXTERNAL_OES;\nimport static android.opengl.GLES20.GL_FLOAT;\nimport static android.opengl.GLES20.GL_FRAGMENT_SHADER;\nimport static android.opengl.GLES20.GL_TRIANGLES;\nimport static android.opengl.GLES20.GL_VERTEX_SHADER;\nimport static android.opengl.GLES20.glActiveTexture;\nimport static android.opengl.GLES20.glAttachShader;\nimport static android.opengl.GLES20.glBindTexture;\nimport static android.opengl.GLES20.glCompileShader;\nimport static android.opengl.GLES20.glCreateProgram;\nimport static android.opengl.GLES20.glCreateShader;\nimport static android.opengl.GLES20.glDrawArrays;\nimport static android.opengl.GLES20.glEnableVertexAttribArray;\nimport static android.opengl.GLES20.glGetAttribLocation;\nimport static android.opengl.GLES20.glGetError;\nimport static android.opengl.GLES20.glGetUniformLocation;\nimport static android.opengl.GLES20.glLinkProgram;\nimport static android.opengl.GLES20.glShaderSource;\nimport static android.opengl.GLES20.glUniform1i;\nimport static android.opengl.GLES20.glUniformMatrix4fv;\nimport static android.opengl.GLES20.glUseProgram;\nimport static android.opengl.GLES20.glVertexAttribPointer;\n\n/**\n * Created by lb6905 on 2017/6/12.\n */\n\npublic class FilterEngine {\n\n    private static FilterEngine filterEngine = null;\n\n    private Context mContext;\n    private FloatBuffer mBuffer;\n    private int mOESTextureId = -1;\n    private int vertexShader = -1;\n    private int fragmentShader = -1;\n\n    private int mShaderProgram = -1;\n\n    private int aPositionLocation = -1;\n    private int aTextureCoordLocation = -1;\n    private int uTextureMatrixLocation = -1;\n    private int uTextureSamplerLocation = -1;\n\n    public FilterEngine(int OESTextureId, Context context) {\n        mContext = context;\n        mOESTextureId = OESTextureId;\n        mBuffer = createBuffer(vertexData);\n        vertexShader = loadShader(GL_VERTEX_SHADER, Utils.readShaderFromResource(mContext, R.raw.base_vertex_shader));\n        fragmentShader = loadShader(GL_FRAGMENT_SHADER, Utils.readShaderFromResource(mContext, R.raw.base_fragment_shader));\n        mShaderProgram = linkProgram(vertexShader, fragmentShader);\n    }\n\n    /*public static FilterEngine getInstance() {\n        if (filterEngine == null) {\n            synchronized (FilterEngine.class) {\n                if (filterEngine == null)\n                    filterEngine = new FilterEngine();\n            }\n        }\n        return filterEngine;\n    }*/\n\n    private static final float[] vertexData = {\n            1f, 1f, 1f, 1f,\n            -1f, 1f, 0f, 1f,\n            -1f, -1f, 0f, 0f,\n            1f, 1f, 1f, 1f,\n            -1f, -1f, 0f, 0f,\n            1f, -1f, 1f, 0f\n    };\n\n    public static final String POSITION_ATTRIBUTE = \"aPosition\";\n    public static final String TEXTURE_COORD_ATTRIBUTE = \"aTextureCoordinate\";\n    public static final String TEXTURE_MATRIX_UNIFORM = \"uTextureMatrix\";\n    public static final String TEXTURE_SAMPLER_UNIFORM = \"uTextureSampler\";\n\n    public FloatBuffer createBuffer(float[] vertexData) {\n        FloatBuffer buffer = ByteBuffer.allocateDirect(vertexData.length * 4)\n                .order(ByteOrder.nativeOrder())\n                .asFloatBuffer();\n        buffer.put(vertexData, 0, vertexData.length).position(0);\n        return buffer;\n    }\n\n    public int loadShader(int type, String shaderSource) {\n        int shader = glCreateShader(type);\n        if (shader == 0) {\n            throw new RuntimeException(\"Create Shader Failed!\" + glGetError());\n        }\n        glShaderSource(shader, shaderSource);\n        glCompileShader(shader);\n        return shader;\n    }\n\n    public int linkProgram(int verShader, int fragShader) {\n        int program = glCreateProgram();\n        if (program == 0) {\n            throw new RuntimeException(\"Create Program Failed!\" + glGetError());\n        }\n        glAttachShader(program, verShader);\n        glAttachShader(program, fragShader);\n        glLinkProgram(program);\n\n        glUseProgram(program);\n        return program;\n    }\n\n    public void drawTexture(float[] transformMatrix) {\n        aPositionLocation = glGetAttribLocation(mShaderProgram, FilterEngine.POSITION_ATTRIBUTE);\n        aTextureCoordLocation = glGetAttribLocation(mShaderProgram, FilterEngine.TEXTURE_COORD_ATTRIBUTE);\n        uTextureMatrixLocation = glGetUniformLocation(mShaderProgram, FilterEngine.TEXTURE_MATRIX_UNIFORM);\n        uTextureSamplerLocation = glGetUniformLocation(mShaderProgram, FilterEngine.TEXTURE_SAMPLER_UNIFORM);\n\n        glActiveTexture(GLES20.GL_TEXTURE0);\n        glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mOESTextureId);\n        glUniform1i(uTextureSamplerLocation, 0);\n        glUniformMatrix4fv(uTextureMatrixLocation, 1, false, transformMatrix, 0);\n\n        if (mBuffer != null) {\n            mBuffer.position(0);\n            glEnableVertexAttribArray(aPositionLocation);\n            glVertexAttribPointer(aPositionLocation, 2, GL_FLOAT, false, 16, mBuffer);\n\n            mBuffer.position(2);\n            glEnableVertexAttribArray(aTextureCoordLocation);\n            glVertexAttribPointer(aTextureCoordLocation, 2, GL_FLOAT, false, 16, mBuffer);\n\n            glDrawArrays(GL_TRIANGLES, 0, 6);\n        }\n    }\n\n    public int getShaderProgram() {\n        return mShaderProgram;\n    }\n\n    public FloatBuffer getBuffer() {\n        return mBuffer;\n    }\n\n    public int getOESTextureId() {\n        return mOESTextureId;\n    }\n\n    public void setOESTextureId(int OESTextureId) {\n        mOESTextureId = OESTextureId;\n    }\n}\n\n"
  },
  {
    "path": "Filter/app/src/main/java/com/liubing/filtertestbed/Utils.java",
    "content": "package com.liubing.filtertestbed;\n\nimport android.content.Context;\nimport android.opengl.GLES11Ext;\nimport android.opengl.GLES20;\n\nimport java.io.BufferedReader;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\n\nimport javax.microedition.khronos.opengles.GL10;\n\n/**\n * Created by lb6905 on 2017/6/28.\n */\n\npublic class Utils {\n\n    public static int createOESTextureObject() {\n        int[] tex = new int[1];\n        GLES20.glGenTextures(1, tex, 0);\n        GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, tex[0]);\n        GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,\n                GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);\n        GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,\n                GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);\n        GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,\n                GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);\n        GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,\n                GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);\n        GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0);\n        return tex[0];\n    }\n\n    public static String readShaderFromResource(Context context, int resourceId) {\n        StringBuilder builder = new StringBuilder();\n        InputStream is = null;\n        InputStreamReader isr = null;\n        BufferedReader br = null;\n        try {\n            is = context.getResources().openRawResource(resourceId);\n            isr = new InputStreamReader(is);\n            br = new BufferedReader(isr);\n            String line;\n            while ((line = br.readLine()) != null) {\n                builder.append(line + \"\\n\");\n            }\n        } catch (IOException e) {\n            e.printStackTrace();\n        } finally {\n            try {\n                if (is != null) {\n                    is.close();\n                    is = null;\n                }\n                if (isr != null) {\n                    isr.close();\n                    isr = null;\n                }\n                if (br != null) {\n                    br.close();\n                    br = null;\n                }\n            } catch (IOException e) {\n                e.printStackTrace();\n            }\n        }\n        return builder.toString();\n    }\n}\n"
  },
  {
    "path": "Filter/app/src/main/res/raw/base_fragment_shader.glsl",
    "content": "#extension GL_OES_EGL_image_external : require\nprecision mediump float;\nuniform samplerExternalOES uTextureSampler;\nvarying vec2 vTextureCoord;\nvoid main()\n{\n  vec4 vCameraColor = texture2D(uTextureSampler, vTextureCoord);\n  float fGrayColor = (0.3*vCameraColor.r + 0.59*vCameraColor.g + 0.11*vCameraColor.b);\n  gl_FragColor = vec4(fGrayColor, fGrayColor, fGrayColor, 1.0);\n}\n"
  },
  {
    "path": "Filter/app/src/main/res/raw/base_vertex_shader.glsl",
    "content": "attribute vec4 aPosition;\nuniform mat4 uTextureMatrix;\nattribute vec4 aTextureCoordinate;\nvarying vec2 vTextureCoord;\nvoid main()\n{\n  vTextureCoord = (uTextureMatrix * aTextureCoordinate).xy;\n  gl_Position = aPosition;\n}"
  },
  {
    "path": "Filter/app/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#3F51B5</color>\n    <color name=\"colorPrimaryDark\">#303F9F</color>\n    <color name=\"colorAccent\">#FF4081</color>\n</resources>\n"
  },
  {
    "path": "Filter/app/src/main/res/values/dimens.xml",
    "content": "<resources>\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"activity_horizontal_margin\">16dp</dimen>\n    <dimen name=\"activity_vertical_margin\">16dp</dimen>\n</resources>\n"
  },
  {
    "path": "Filter/app/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">FilterTestBed</string>\n</resources>\n"
  },
  {
    "path": "Filter/app/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar\">\n        <!-- Customize your theme here. -->\n        <item name=\"colorPrimary\">@color/colorPrimary</item>\n        <item name=\"colorPrimaryDark\">@color/colorPrimaryDark</item>\n        <item name=\"colorAccent\">@color/colorAccent</item>\n    </style>\n\n</resources>\n"
  },
  {
    "path": "Filter/app/src/main/res/values-w820dp/dimens.xml",
    "content": "<resources>\n    <!-- Example customization of dimensions originally defined in res/values/dimens.xml\n         (such as screen margins) for screens with more than 820dp of available width. This\n         would include 7\" and 10\" devices in landscape (~960dp and ~1280dp respectively). -->\n    <dimen name=\"activity_horizontal_margin\">64dp</dimen>\n</resources>\n"
  },
  {
    "path": "Filter/build.gradle",
    "content": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n    repositories {\n        jcenter()\n    }\n    dependencies {\n        classpath 'com.android.tools.build:gradle:2.3.0'\n\n        // NOTE: Do not place your application dependencies here; they belong\n        // in the individual module build.gradle files\n    }\n}\n\nallprojects {\n    repositories {\n        jcenter()\n    }\n}\n\ntask clean(type: Delete) {\n    delete rootProject.buildDir\n}\n"
  },
  {
    "path": "Filter/gradle/wrapper/gradle-wrapper.properties",
    "content": "#Wed Oct 21 11:34:03 PDT 2015\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-3.5-all.zip\n"
  },
  {
    "path": "Filter/gradle.properties",
    "content": "# Project-wide Gradle settings.\n\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will override*\n# any settings specified in this file.\n\n# For more details on how to configure your build environment visit\n# http://www.gradle.org/docs/current/userguide/build_environment.html\n\n# Specifies the JVM arguments used for the daemon process.\n# The setting is particularly useful for tweaking memory settings.\n# Default value: -Xmx10248m -XX:MaxPermSize=256m\n# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8\n\n# When configured, Gradle will run in incubating parallel mode.\n# This option should only be used with decoupled projects. More details, visit\n# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects\n# org.gradle.parallel=true"
  },
  {
    "path": "Filter/gradlew",
    "content": "#!/usr/bin/env bash\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS=\"\"\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn ( ) {\n    echo \"$*\"\n}\n\ndie ( ) {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\nesac\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done\n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules\nfunction splitJvmOpts() {\n    JVM_OPTS=(\"$@\")\n}\neval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\nJVM_OPTS[${#JVM_OPTS[*]}]=\"-Dorg.gradle.appname=$APP_BASE_NAME\"\n\nexec \"$JAVACMD\" \"${JVM_OPTS[@]}\" -classpath \"$CLASSPATH\" org.gradle.wrapper.GradleWrapperMain \"$@\"\n"
  },
  {
    "path": "Filter/gradlew.bat",
    "content": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem  Gradle startup script for Windows\n@rem\n@rem ##########################################################################\n\n@rem Set local scope for the variables with windows NT shell\nif \"%OS%\"==\"Windows_NT\" setlocal\n\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nset DEFAULT_JVM_OPTS=\n\nset DIRNAME=%~dp0\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\nset APP_BASE_NAME=%~n0\nset APP_HOME=%DIRNAME%\n\n@rem Find java.exe\nif defined JAVA_HOME goto findJavaFromJavaHome\n\nset JAVA_EXE=java.exe\n%JAVA_EXE% -version >NUL 2>&1\nif \"%ERRORLEVEL%\" == \"0\" goto init\n\necho.\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:findJavaFromJavaHome\nset JAVA_HOME=%JAVA_HOME:\"=%\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\n\nif exist \"%JAVA_EXE%\" goto init\n\necho.\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:init\n@rem Get command-line arguments, handling Windowz variants\n\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\nif \"%@eval[2+2]\" == \"4\" goto 4NT_args\n\n:win9xME_args\n@rem Slurp the command line arguments.\nset CMD_LINE_ARGS=\nset _SKIP=2\n\n:win9xME_args_slurp\nif \"x%~1\" == \"x\" goto execute\n\nset CMD_LINE_ARGS=%*\ngoto execute\n\n:4NT_args\n@rem Get arguments from the 4NT Shell from JP Software\nset CMD_LINE_ARGS=%$\n\n:execute\n@rem Setup the command line\n\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\n\n@rem Execute Gradle\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\n\n:end\n@rem End local scope for the variables with windows NT shell\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\n\n:fail\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\nrem the _cmd.exe /c_ return code!\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\nexit /b 1\n\n:mainEnd\nif \"%OS%\"==\"Windows_NT\" endlocal\n\n:omega\n"
  },
  {
    "path": "Filter/settings.gradle",
    "content": "include ':app'\n"
  },
  {
    "path": "JNIDemo/.gitignore",
    "content": "*.iml\n.gradle\n/local.properties\n/.idea/workspace.xml\n/.idea/libraries\n.DS_Store\n/build\n/captures\n.externalNativeBuild\n"
  },
  {
    "path": "JNIDemo/app/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "JNIDemo/app/build.gradle",
    "content": "apply plugin: 'com.android.application'\n\nandroid {\n    compileSdkVersion 25\n    buildToolsVersion \"25.0.2\"\n    defaultConfig {\n        applicationId \"com.lb6905.jnidemo\"\n        minSdkVersion 15\n        targetSdkVersion 25\n        versionCode 1\n        versionName \"1.0\"\n        testInstrumentationRunner \"android.support.test.runner.AndroidJUnitRunner\"\n\n        sourceSets.main {\n            jniLibs.srcDir 'src/main/libs'\n            jni.srcDirs = []\n        }\n    }\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n        }\n    }\n}\n\ndependencies {\n    compile fileTree(dir: 'libs', include: ['*.jar'])\n    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {\n        exclude group: 'com.android.support', module: 'support-annotations'\n    })\n    compile 'com.android.support:appcompat-v7:25.3.1'\n    compile 'com.android.support.constraint:constraint-layout:1.0.2'\n    testCompile 'junit:junit:4.12'\n}\n"
  },
  {
    "path": "JNIDemo/app/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in E:\\ProgramFiles\\Android\\sdk/tools/proguard/proguard-android.txt\n# You can edit the include path and order by changing the proguardFiles\n# directive in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# Add any project specific keep options here:\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n\n# Uncomment this to preserve the line number information for\n# debugging stack traces.\n#-keepattributes SourceFile,LineNumberTable\n\n# If you keep the line number information, uncomment this to\n# hide the original source file name.\n#-renamesourcefileattribute SourceFile\n"
  },
  {
    "path": "JNIDemo/app/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n          package=\"com.lb6905.jnidemo\">\n\n    <application\n        android:allowBackup=\"true\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:roundIcon=\"@mipmap/ic_launcher_round\"\n        android:supportsRtl=\"true\"\n        android:theme=\"@style/AppTheme\">\n        <activity android:name=\".MainActivity\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\"/>\n\n                <category android:name=\"android.intent.category.LAUNCHER\"/>\n            </intent-filter>\n        </activity>\n    </application>\n\n</manifest>"
  },
  {
    "path": "JNIDemo/app/src/main/java/com/lb6905/jnidemo/MainActivity.java",
    "content": "package com.lb6905.jnidemo;\n\nimport android.support.v7.app.AppCompatActivity;\nimport android.os.Bundle;\nimport android.widget.TextView;\n\npublic class MainActivity extends AppCompatActivity {\n    private TextView mTextView;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_main);\n        mTextView = (TextView) findViewById(R.id.tv_jni);\n        int[] arr = getArray();\n        mTextView.setText(stringFromJNI());\n        JNIReflect();\n    }\n\n    public native String stringFromJNI();\n    public native void setArray(int[] array);\n    public native int[] getArray();\n    public native void JNIReflect();\n\n    static {\n        System.loadLibrary(\"hello-jni\");\n    }\n}\n"
  },
  {
    "path": "JNIDemo/app/src/main/java/com/lb6905/jnidemo/TestClass.java",
    "content": "package com.lb6905.jnidemo;\n\nimport android.util.Log;\n\n/**\n * Created by lb6905 on 2017/7/18.\n */\n\npublic class TestClass {\n    private final static String TAG = \"TestClass\";\n\n    public TestClass(){\n        Log.i(TAG, \"TestClass\");\n    }\n\n    public void test(int index) {\n        Log.i(TAG, \"test : \" + index);\n    }\n\n    public static void testStatic(String str) {\n        Log.i(TAG, \"testStatic : \" + str);\n    }\n\n    public static class InnerClass {\n        private int num;\n        public InnerClass() {\n            Log.i(TAG, \"InnerClass\");\n        }\n\n        public void setInt(int n) {\n            num = n;\n            Log.i(TAG, \"setInt: num = \" + num);\n        }\n    }\n}\n"
  },
  {
    "path": "JNIDemo/app/src/main/jni/Android.mk",
    "content": "# Copyright (C) 2009 The Android Open Source Project\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\nLOCAL_PATH := $(call my-dir)\n\ninclude $(CLEAR_VARS)\n\nLOCAL_MODULE    := hello-jni\nLOCAL_SRC_FILES := hello-jni.c\n\ninclude $(BUILD_SHARED_LIBRARY)\n"
  },
  {
    "path": "JNIDemo/app/src/main/jni/hello-jni.c",
    "content": "//\n// Created by lb6905 on 2017/6/21.\n//\n#include <jni.h>\n#include <string.h>\n\n#ifndef _Included_com_lb6905_jnidemo_MainActivity\n#define _Included_com_lb6905_jnidemo_MainActivity\n\nint lutData[5] = {0,10,12,3,4};\n\njstring\nJava_com_lb6905_jnidemo_MainActivity_stringFromJNI( JNIEnv* env,\n                                                  jobject thiz )\n{\n    return (*env)->NewStringUTF(env, \"Hello from JNI !\");\n}\n\n/*\n * Class:     com_lb6905_jnidemo_MainActivity\n * Method:    setArray\n * Signature: ([I)V\n */\nJNIEXPORT void JNICALL Java_com_lb6905_jnidemo_MainActivity_setArray\n  (JNIEnv *env, jobject thiz, jintArray array)\n  {\n\n  }\n\n/*\n * Class:     com_lb6905_jnidemo_MainActivity\n * Method:    getArray\n * Signature: ()[I\n */\nJNIEXPORT jintArray JNICALL Java_com_lb6905_jnidemo_MainActivity_getArray\n  (JNIEnv *env, jobject thiz)\n  {\n    jintArray array = (*env)->NewIntArray(env, 5);\n    (*env)->SetIntArrayRegion(env, array, 0, 5, lutData);\n    return array;\n  }\n\n  JNIEXPORT void JNICALL Java_com_lb6905_jnidemo_MainActivity_JNIReflect\n    (JNIEnv *env, jobject thiz)\n    {\n        //实例化Test类\n        jclass testclass = (*env)->FindClass(env, \"com/lb6905/jnidemo/TestClass\");\n        jmethodID testcontruct = (*env)->GetMethodID(env, testclass, \"<init>\", \"()V\");\n        jobject testobject = (*env)->NewObject(env, testclass, testcontruct);\n\n        //调用成员方法\n        jmethodID test = (*env)->GetMethodID(env, testclass, \"test\", \"(I)V\");\n        (*env)->CallVoidMethod(env, testobject, test, 1);\n\n        //调用静态方法\n        jmethodID testStatic = (*env)->GetStaticMethodID(env, testclass, \"testStatic\", \"(Ljava/lang/String;)V\");\n        jstring str = (*env)->NewStringUTF(env, \"hello world!\");\n        (*env)->CallStaticVoidMethod(env, testclass, testStatic, str);\n\n        //实例化InnerClass子类\n        jclass innerclass = (*env)->FindClass(env, \"com/lb6905/jnidemo/TestClass$InnerClass\");\n        jmethodID innercontruct = (*env)->GetMethodID(env, innerclass, \"<init>\", \"()V\");\n        jobject innerobject = (*env)->NewObject(env, innerclass, innercontruct);\n\n        jmethodID setInt = (*env)->GetMethodID(env, innerclass, \"setInt\", \"(I)V\");\n        (*env)->CallVoidMethod(env, innerobject, setInt, 2);\n    }\n  #endif"
  },
  {
    "path": "JNIDemo/app/src/main/obj/local/arm64-v8a/objs/hello-jni/hello-jni.o.d",
    "content": "F:/Apps/jniDemo/JNIDemo/app/src/main/obj/local/arm64-v8a/objs/hello-jni/hello-jni.o: \\\n  F:/Apps/jniDemo/JNIDemo/app/src/main/jni/hello-jni.c\n"
  },
  {
    "path": "JNIDemo/app/src/main/obj/local/armeabi/objs/hello-jni/hello-jni.o.d",
    "content": "F:/Apps/jniDemo/JNIDemo/app/src/main/obj/local/armeabi/objs/hello-jni/hello-jni.o: \\\n  F:/Apps/jniDemo/JNIDemo/app/src/main/jni/hello-jni.c\n"
  },
  {
    "path": "JNIDemo/app/src/main/obj/local/armeabi-v7a/objs/hello-jni/hello-jni.o.d",
    "content": "F:/Apps/jniDemo/JNIDemo/app/src/main/obj/local/armeabi-v7a/objs/hello-jni/hello-jni.o: \\\n  F:/Apps/jniDemo/JNIDemo/app/src/main/jni/hello-jni.c\n"
  },
  {
    "path": "JNIDemo/app/src/main/obj/local/mips/objs/hello-jni/hello-jni.o.d",
    "content": "F:/Apps/jniDemo/JNIDemo/app/src/main/obj/local/mips/objs/hello-jni/hello-jni.o: \\\n  F:/Apps/jniDemo/JNIDemo/app/src/main/jni/hello-jni.c\n"
  },
  {
    "path": "JNIDemo/app/src/main/obj/local/mips64/objs/hello-jni/hello-jni.o.d",
    "content": "F:/Apps/jniDemo/JNIDemo/app/src/main/obj/local/mips64/objs/hello-jni/hello-jni.o: \\\n  F:/Apps/jniDemo/JNIDemo/app/src/main/jni/hello-jni.c\n"
  },
  {
    "path": "JNIDemo/app/src/main/obj/local/x86/objs/hello-jni/hello-jni.o.d",
    "content": "F:/Apps/jniDemo/JNIDemo/app/src/main/obj/local/x86/objs/hello-jni/hello-jni.o: \\\n  F:/Apps/jniDemo/JNIDemo/app/src/main/jni/hello-jni.c\n"
  },
  {
    "path": "JNIDemo/app/src/main/obj/local/x86_64/objs/hello-jni/hello-jni.o.d",
    "content": "F:/Apps/jniDemo/JNIDemo/app/src/main/obj/local/x86_64/objs/hello-jni/hello-jni.o: \\\n  F:/Apps/jniDemo/JNIDemo/app/src/main/jni/hello-jni.c\n"
  },
  {
    "path": "JNIDemo/app/src/main/res/layout/activity_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<android.support.constraint.ConstraintLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:context=\"com.lb6905.jnidemo.MainActivity\">\n\n    <TextView\n        android:id=\"@+id/tv_jni\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"Hello World!\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintLeft_toLeftOf=\"parent\"\n        app:layout_constraintRight_toRightOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\"/>\n\n</android.support.constraint.ConstraintLayout>\n"
  },
  {
    "path": "JNIDemo/app/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#3F51B5</color>\n    <color name=\"colorPrimaryDark\">#303F9F</color>\n    <color name=\"colorAccent\">#FF4081</color>\n</resources>\n"
  },
  {
    "path": "JNIDemo/app/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">JNIDemo</string>\n</resources>\n"
  },
  {
    "path": "JNIDemo/app/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar\">\n        <!-- Customize your theme here. -->\n        <item name=\"colorPrimary\">@color/colorPrimary</item>\n        <item name=\"colorPrimaryDark\">@color/colorPrimaryDark</item>\n        <item name=\"colorAccent\">@color/colorAccent</item>\n    </style>\n\n</resources>\n"
  },
  {
    "path": "JNIDemo/build.gradle",
    "content": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n    repositories {\n        jcenter()\n    }\n    dependencies {\n        classpath 'com.android.tools.build:gradle:2.3.0'\n\n        // NOTE: Do not place your application dependencies here; they belong\n        // in the individual module build.gradle files\n    }\n}\n\nallprojects {\n    repositories {\n        jcenter()\n    }\n}\n\ntask clean(type: Delete) {\n    delete rootProject.buildDir\n}\n"
  },
  {
    "path": "JNIDemo/gradle/wrapper/gradle-wrapper.properties",
    "content": "#Wed Jun 21 09:31:24 CST 2017\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-3.5-all.zip\n"
  },
  {
    "path": "JNIDemo/gradle.properties",
    "content": "# Project-wide Gradle settings.\n\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will override*\n# any settings specified in this file.\n\n# For more details on how to configure your build environment visit\n# http://www.gradle.org/docs/current/userguide/build_environment.html\n\n# Specifies the JVM arguments used for the daemon process.\n# The setting is particularly useful for tweaking memory settings.\norg.gradle.jvmargs=-Xmx1536m\nandroid.useDeprecatedNDK=true\n\n# When configured, Gradle will run in incubating parallel mode.\n# This option should only be used with decoupled projects. More details, visit\n# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects\n# org.gradle.parallel=true\n"
  },
  {
    "path": "JNIDemo/gradlew",
    "content": "#!/usr/bin/env bash\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS=\"\"\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn ( ) {\n    echo \"$*\"\n}\n\ndie ( ) {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\nesac\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done\n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules\nfunction splitJvmOpts() {\n    JVM_OPTS=(\"$@\")\n}\neval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\nJVM_OPTS[${#JVM_OPTS[*]}]=\"-Dorg.gradle.appname=$APP_BASE_NAME\"\n\nexec \"$JAVACMD\" \"${JVM_OPTS[@]}\" -classpath \"$CLASSPATH\" org.gradle.wrapper.GradleWrapperMain \"$@\"\n"
  },
  {
    "path": "JNIDemo/gradlew.bat",
    "content": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem  Gradle startup script for Windows\n@rem\n@rem ##########################################################################\n\n@rem Set local scope for the variables with windows NT shell\nif \"%OS%\"==\"Windows_NT\" setlocal\n\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nset DEFAULT_JVM_OPTS=\n\nset DIRNAME=%~dp0\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\nset APP_BASE_NAME=%~n0\nset APP_HOME=%DIRNAME%\n\n@rem Find java.exe\nif defined JAVA_HOME goto findJavaFromJavaHome\n\nset JAVA_EXE=java.exe\n%JAVA_EXE% -version >NUL 2>&1\nif \"%ERRORLEVEL%\" == \"0\" goto init\n\necho.\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:findJavaFromJavaHome\nset JAVA_HOME=%JAVA_HOME:\"=%\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\n\nif exist \"%JAVA_EXE%\" goto init\n\necho.\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:init\n@rem Get command-line arguments, handling Windowz variants\n\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\nif \"%@eval[2+2]\" == \"4\" goto 4NT_args\n\n:win9xME_args\n@rem Slurp the command line arguments.\nset CMD_LINE_ARGS=\nset _SKIP=2\n\n:win9xME_args_slurp\nif \"x%~1\" == \"x\" goto execute\n\nset CMD_LINE_ARGS=%*\ngoto execute\n\n:4NT_args\n@rem Get arguments from the 4NT Shell from JP Software\nset CMD_LINE_ARGS=%$\n\n:execute\n@rem Setup the command line\n\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\n\n@rem Execute Gradle\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\n\n:end\n@rem End local scope for the variables with windows NT shell\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\n\n:fail\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\nrem the _cmd.exe /c_ return code!\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\nexit /b 1\n\n:mainEnd\nif \"%OS%\"==\"Windows_NT\" endlocal\n\n:omega\n"
  },
  {
    "path": "JNIDemo/settings.gradle",
    "content": "include ':app'\n"
  },
  {
    "path": "OpenGLES/.gitignore",
    "content": "*.iml\n.gradle\n/local.properties\n/.idea/workspace.xml\n/.idea/libraries\n.DS_Store\n/build\n/captures\n.externalNativeBuild\n"
  },
  {
    "path": "OpenGLES/app/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "OpenGLES/app/build.gradle",
    "content": "apply plugin: 'com.android.application'\n\nandroid {\n    compileSdkVersion 25\n    buildToolsVersion \"25.0.2\"\n    defaultConfig {\n        applicationId \"com.lb377463323.opengles\"\n        minSdkVersion 15\n        targetSdkVersion 25\n        versionCode 1\n        versionName \"1.0\"\n    }\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n        }\n    }\n}\n\ndependencies {\n    compile fileTree(dir: 'libs', include: ['*.jar'])\n    compile 'com.android.support:appcompat-v7:25.3.1'\n}\n"
  },
  {
    "path": "OpenGLES/app/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in E:\\ProgramFiles\\Android\\sdk/tools/proguard/proguard-android.txt\n# You can edit the include path and order by changing the proguardFiles\n# directive in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# Add any project specific keep options here:\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n\n# Uncomment this to preserve the line number information for\n# debugging stack traces.\n#-keepattributes SourceFile,LineNumberTable\n\n# If you keep the line number information, uncomment this to\n# hide the original source file name.\n#-renamesourcefileattribute SourceFile\n"
  },
  {
    "path": "OpenGLES/app/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n          package=\"com.lb377463323.opengles\">\n\n    <application\n        android:allowBackup=\"true\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:roundIcon=\"@mipmap/ic_launcher_round\"\n        android:supportsRtl=\"true\"\n        android:theme=\"@style/AppTheme\">\n        <activity android:name=\".GLActivity\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\"/>\n\n                <category android:name=\"android.intent.category.LAUNCHER\"/>\n            </intent-filter>\n        </activity>\n    </application>\n\n</manifest>"
  },
  {
    "path": "OpenGLES/app/src/main/java/com/lb377463323/opengles/GLActivity.java",
    "content": "package com.lb377463323.opengles;\n\nimport android.content.pm.ActivityInfo;\nimport android.opengl.GLSurfaceView;\nimport android.support.v7.app.AppCompatActivity;\nimport android.os.Bundle;\nimport android.view.Window;\nimport android.view.WindowManager;\n\npublic class GLActivity extends AppCompatActivity {\n    private GLSurfaceView mGLSurfaceView;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n\n        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);\n        requestWindowFeature(Window.FEATURE_NO_TITLE);\n        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);\n\n        mGLSurfaceView = new GLSurfaceView(this);\n        mGLSurfaceView.setEGLContextClientVersion(2);\n        mGLSurfaceView.setRenderer(new GLRenderer());\n        setContentView(mGLSurfaceView);\n    }\n}\n"
  },
  {
    "path": "OpenGLES/app/src/main/java/com/lb377463323/opengles/GLRenderer.java",
    "content": "package com.lb377463323.opengles;\n\nimport android.opengl.GLES20;\nimport android.opengl.GLSurfaceView;\nimport android.opengl.Matrix;\n\nimport javax.microedition.khronos.egl.EGLConfig;\nimport javax.microedition.khronos.opengles.GL10;\n\n/**\n * Created by lb6905 on 2017/6/30.\n */\n\npublic class GLRenderer implements GLSurfaceView.Renderer {\n    private Triangle mTriangle;\n    private float[] mMVPMatrix = new float[16];\n    private float[] mProjectMatrix = new float[16];\n    private float[] mViewMatrix = new float[16];\n\n    @Override\n    public void onSurfaceCreated(GL10 gl, EGLConfig config) {\n        GLES20.glClearColor(0, 0, 0, 1);\n        mTriangle = new Triangle();\n\n        //设置相机位置\n        Matrix.setLookAtM(mViewMatrix, 0, 0, 0, 3.0f, 0f, 0f, 0f, 0f, 1.0f, 0.0f);\n    }\n\n    @Override\n    public void onSurfaceChanged(GL10 gl, int width, int height) {\n        GLES20.glViewport(0, 0, width, height);\n        //计算宽高比\n        float ratio = (float) height / width;\n        //设置透视投影\n        Matrix.frustumM(mProjectMatrix, 0, -1, 1, -ratio, ratio, 3, 7);\n\n        //计算变换矩阵\n        Matrix.multiplyMM(mMVPMatrix, 0, mProjectMatrix, 0, mViewMatrix, 0);\n    }\n\n    @Override\n    public void onDrawFrame(GL10 gl) {\n        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);\n        mTriangle.draw(mMVPMatrix);\n    }\n}\n"
  },
  {
    "path": "OpenGLES/app/src/main/java/com/lb377463323/opengles/Triangle.java",
    "content": "package com.lb377463323.opengles;\n\nimport android.opengl.GLES20;\n\nimport java.nio.ByteBuffer;\nimport java.nio.ByteOrder;\nimport java.nio.FloatBuffer;\n\nimport static android.opengl.GLES20.GL_FLOAT;\n\n/**\n * Created by lb6905 on 2017/6/30.\n */\n\npublic class Triangle {\n    private FloatBuffer vertexBuffer;\n\n    static final int COORDS_PER_VERTEX = 3;\n    private final int mProgram;\n\n    private int mPositionHandle;\n    private int mColorHandle;\n    private int mMVPMatrixHandle;\n\n    private final int vertexCount = triangleCoords.length;\n    private final int vertexStride = COORDS_PER_VERTEX * 4;\n\n    /*private final String vertexShaderCode =\n            \"attribute vec4 vPosition;\" +\n                    \"void main() {\" +\n                    \"  gl_Position = vPosition;\" +\n                    \"}\";*/\n\n    private final String vertexShaderCode =\n            \"uniform mat4 uMVPMatrix;\" +\n            \"attribute vec4 vPosition;\" +\n            \"void main() {\" +\n            \"  gl_Position = uMVPMatrix * vPosition;\" +\n            \"}\";\n\n    private final String fragmentShaderCode =\n            \"precision mediump float;\"\n            + \"uniform vec4 vColor;\"\n            + \"void main() {\"\n            + \"  gl_FragColor = vColor;\"\n            + \"}\";\n\n    static float[] triangleCoords = {\n            0.0f, 1.0f, 0.0f,\n            0.0f, 0.0f, 0.0f,\n            1.0f, 0.0f, 0.0f\n    };\n\n    float[] color = {0.0f, 1f, 0f, 1.0f};\n\n\n    public Triangle() {\n        ByteBuffer bb = ByteBuffer.allocateDirect(triangleCoords.length * 4);\n        bb.order(ByteOrder.nativeOrder());\n\n        vertexBuffer = bb.asFloatBuffer();\n        vertexBuffer.put(triangleCoords);\n        vertexBuffer.position(0);\n\n        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);\n        int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);\n\n        mProgram = GLES20.glCreateProgram();\n        GLES20.glAttachShader(mProgram, vertexShader);\n        GLES20.glAttachShader(mProgram, fragmentShader);\n\n        GLES20.glLinkProgram(mProgram);\n    }\n\n    public void draw(float[] mvpMatrix) {\n        GLES20.glUseProgram(mProgram);\n\n        mPositionHandle = GLES20.glGetAttribLocation(mProgram, \"vPosition\");\n\n        GLES20.glEnableVertexAttribArray(mPositionHandle);\n\n        GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,\n                GL_FLOAT, false, vertexStride, vertexBuffer);\n\n        mColorHandle = GLES20.glGetUniformLocation(mProgram, \"vColor\");//此方法名若写错，则绘制出来的图形颜色全是默认黑色\n        GLES20.glUniform4fv(mColorHandle, 1, color, 0);\n\n        mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, \"uMVPMatrix\");\n        GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);\n\n        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);\n\n        GLES20.glDisableVertexAttribArray(mPositionHandle);\n    }\n\n    public static int loadShader(int type, String shaderCode) {\n        int shader = GLES20.glCreateShader(type);\n\n        GLES20.glShaderSource(shader, shaderCode);\n        GLES20.glCompileShader(shader);\n\n        return shader;\n    }\n}\n"
  },
  {
    "path": "OpenGLES/app/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#3F51B5</color>\n    <color name=\"colorPrimaryDark\">#303F9F</color>\n    <color name=\"colorAccent\">#FF4081</color>\n</resources>\n"
  },
  {
    "path": "OpenGLES/app/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">OpenGLES</string>\n</resources>\n"
  },
  {
    "path": "OpenGLES/app/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar\">\n        <!-- Customize your theme here. -->\n        <item name=\"colorPrimary\">@color/colorPrimary</item>\n        <item name=\"colorPrimaryDark\">@color/colorPrimaryDark</item>\n        <item name=\"colorAccent\">@color/colorAccent</item>\n    </style>\n\n</resources>\n"
  },
  {
    "path": "OpenGLES/build.gradle",
    "content": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n    repositories {\n        jcenter()\n    }\n    dependencies {\n        classpath 'com.android.tools.build:gradle:2.3.0'\n\n        // NOTE: Do not place your application dependencies here; they belong\n        // in the individual module build.gradle files\n    }\n}\n\nallprojects {\n    repositories {\n        jcenter()\n    }\n}\n\ntask clean(type: Delete) {\n    delete rootProject.buildDir\n}\n"
  },
  {
    "path": "OpenGLES/gradle/wrapper/gradle-wrapper.properties",
    "content": "#Mon Jul 17 15:58:28 CST 2017\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-3.5-all.zip\n"
  },
  {
    "path": "OpenGLES/gradle.properties",
    "content": "# Project-wide Gradle settings.\n\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will override*\n# any settings specified in this file.\n\n# For more details on how to configure your build environment visit\n# http://www.gradle.org/docs/current/userguide/build_environment.html\n\n# Specifies the JVM arguments used for the daemon process.\n# The setting is particularly useful for tweaking memory settings.\norg.gradle.jvmargs=-Xmx1536m\n\n# When configured, Gradle will run in incubating parallel mode.\n# This option should only be used with decoupled projects. More details, visit\n# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects\n# org.gradle.parallel=true\n"
  },
  {
    "path": "OpenGLES/gradlew",
    "content": "#!/usr/bin/env bash\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS=\"\"\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn ( ) {\n    echo \"$*\"\n}\n\ndie ( ) {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\nesac\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done\n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules\nfunction splitJvmOpts() {\n    JVM_OPTS=(\"$@\")\n}\neval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\nJVM_OPTS[${#JVM_OPTS[*]}]=\"-Dorg.gradle.appname=$APP_BASE_NAME\"\n\nexec \"$JAVACMD\" \"${JVM_OPTS[@]}\" -classpath \"$CLASSPATH\" org.gradle.wrapper.GradleWrapperMain \"$@\"\n"
  },
  {
    "path": "OpenGLES/gradlew.bat",
    "content": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem  Gradle startup script for Windows\n@rem\n@rem ##########################################################################\n\n@rem Set local scope for the variables with windows NT shell\nif \"%OS%\"==\"Windows_NT\" setlocal\n\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nset DEFAULT_JVM_OPTS=\n\nset DIRNAME=%~dp0\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\nset APP_BASE_NAME=%~n0\nset APP_HOME=%DIRNAME%\n\n@rem Find java.exe\nif defined JAVA_HOME goto findJavaFromJavaHome\n\nset JAVA_EXE=java.exe\n%JAVA_EXE% -version >NUL 2>&1\nif \"%ERRORLEVEL%\" == \"0\" goto init\n\necho.\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:findJavaFromJavaHome\nset JAVA_HOME=%JAVA_HOME:\"=%\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\n\nif exist \"%JAVA_EXE%\" goto init\n\necho.\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:init\n@rem Get command-line arguments, handling Windowz variants\n\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\nif \"%@eval[2+2]\" == \"4\" goto 4NT_args\n\n:win9xME_args\n@rem Slurp the command line arguments.\nset CMD_LINE_ARGS=\nset _SKIP=2\n\n:win9xME_args_slurp\nif \"x%~1\" == \"x\" goto execute\n\nset CMD_LINE_ARGS=%*\ngoto execute\n\n:4NT_args\n@rem Get arguments from the 4NT Shell from JP Software\nset CMD_LINE_ARGS=%$\n\n:execute\n@rem Setup the command line\n\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\n\n@rem Execute Gradle\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\n\n:end\n@rem End local scope for the variables with windows NT shell\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\n\n:fail\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\nrem the _cmd.exe /c_ return code!\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\nexit /b 1\n\n:mainEnd\nif \"%OS%\"==\"Windows_NT\" endlocal\n\n:omega\n"
  },
  {
    "path": "OpenGLES/settings.gradle",
    "content": "include ':app'\n"
  },
  {
    "path": "README.md",
    "content": "# GraphicsTestBed\n\n此项目为学习Android Graphics时写的各种Demo，根据目录排放如下，后面整理好会添加一些滤镜处理和OpenGLES进阶Demo。也欢迎大家有合适的Graphic Demo提交进来，最好带有博客讲解。\n\n- Camera\n\t- CameraV1： 根据Camera第一版API写的\n\t- CameraV2： 根据Camera第二版API写的（[Android Camera2教程之打开相机、开启预览、实现PreviewCallback、拍照](http://blog.csdn.net/lb377463323/article/details/52740411)）\n- JNIDemo\n\t- [Android JNI开发流程](http://blog.csdn.net/lb377463323/article/details/75112049)  \n\t- [Android JNI反射调用Java构造方法、成员方法和静态方法](http://blog.csdn.net/lb377463323/article/details/75303125)\n- OpenGLES\n\t- [OpenGL ES2.0入门之Android篇(一)——绘制三角形](http://blog.csdn.net/lb377463323/article/details/52136518)\n- Filter（此代码包含三个包如下：有三个对应的Activity，在AndroidManifest中取消注释即可运行）\n\t- CameraV1GLSurfaceView：对应博客为 - [Android Camera使用OpenGL ES 2.0和GLSurfaceView对预览进行实时处理（黑白滤镜）](http://blog.csdn.net/lb377463323/article/details/77071054)\n\t- CameraV1TextureView：对应博客为 - [Android Camera使用OpenGL ES 2.0和TextureView对预览进行实时处理（黑白滤镜）](http://blog.csdn.net/lb377463323/article/details/77096652)\n\t- CameraV2GLSurfaceView：对应博客为 - [Android Camera2使用OpenGL ES 2.0和GLSurfaceView对预览进行实时处理（黑白滤镜）](http://blog.csdn.net/lb377463323/article/details/78054892)\n"
  }
]