SmartCamera.java revision 227b47625d7482b5b47ad0e4c70ce0a246236ade
1/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package androidx.media.filterfw.samples.simplecamera;
18
19import android.app.Activity;
20import android.content.Intent;
21import android.graphics.Bitmap;
22import android.graphics.drawable.BitmapDrawable;
23import android.graphics.drawable.Drawable;
24import android.os.Bundle;
25import android.os.Handler;
26import android.provider.MediaStore;
27import android.util.Log;
28import android.view.LayoutInflater;
29import android.view.SurfaceView;
30import android.view.View;
31import android.view.View.OnClickListener;
32import android.widget.AdapterView;
33import android.widget.Button;
34import android.widget.ImageView;
35import android.widget.LinearLayout;
36import android.widget.Spinner;
37import android.widget.TextView;
38import androidx.media.filterfw.FilterGraph;
39import androidx.media.filterfw.GraphReader;
40import androidx.media.filterfw.GraphRunner;
41import androidx.media.filterfw.MffContext;
42
43import java.io.IOException;
44import java.text.SimpleDateFormat;
45import java.util.ArrayList;
46import java.util.Calendar;
47
48
49public class SmartCamera extends Activity {
50
51    private SurfaceView mCameraView;
52    private TextView mGoodBadTextView;
53    private TextView mFPSTextView;
54    private TextView mEyesTextView;
55    private TextView mSmilesTextView;
56    private TextView mScoreTextView;
57    private static ImageView mImageView1;
58    private static ImageView mImageView2;
59    private static ImageView mImageView3;
60    private static ImageView mImageView4;
61    private static ImageView mImageView5;
62    private Button mStartStopButton;
63    private TextView mImagesSavedTextView;
64    private Spinner mSpinner;
65    private LinearLayout mLinearLayout;
66
67    private MffContext mContext;
68    private FilterGraph mGraph;
69    private GraphRunner mRunner;
70    private Handler mHandler = new Handler();
71
72    private static final String TAG = "SmartCamera";
73    private static final boolean sUseFacialExpression = false;
74    private boolean isPendingRunGraph = false;
75
76    private static ArrayList<ImageView> mImages;
77    private static int count = -1;
78    private static boolean countHasReachedMax = false;
79    private static int numImages = 0;
80
81    // Function to return the correct image view to display the current bitmap
82    public static ImageView getImageView() {
83        if (count == numImages-1) countHasReachedMax = true;
84        count = (count+1) % numImages;
85        return mImages.get(count);
86    }
87
88    // Function used to run images through the graph, mainly for CSV data generation
89    public void runGraphOnImage(String filePath, String fileName) {
90        if(fileName.endsWith(".jpg") == false) {
91            return;
92        }
93        mGraph.getVariable("gallerySource").setValue(filePath + "/" + fileName);
94        Log.v(TAG, "runGraphOnImage : : " + filePath + " name: " + fileName);
95        mGraph.getVariable("imageName").setValue(fileName);
96        mGraph.getVariable("filePath").setValue(filePath); // wrong
97        try {
98            Thread.sleep(400);
99        } catch (InterruptedException e) {
100            // TODO Auto-generated catch block
101            e.printStackTrace();
102        }
103    }
104
105    // Function to clear the "Images Saved" text off the screen
106    private void clearImagesSavedTextView() {
107        mImagesSavedTextView.setText("");
108    }
109
110    // Function to capture the images in the current imageviews and save them to the gallery
111    private void captureImages() {
112        ((WaveTriggerFilter) mGraph.getFilter("snapEffect")).trigger();
113        mGraph.getVariable("startCapture").setValue(false);
114        Bitmap bitmap = null;
115        Drawable res = getResources().getDrawable(R.drawable.black_screen);
116        Calendar cal = Calendar.getInstance();
117        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss");
118
119        Log.v(TAG, "numImages: " + numImages + " count: " + count +
120                " hasReachedMax: " + countHasReachedMax);
121        int maxI = countHasReachedMax ? numImages : count+1;
122        if(maxI != 0) {
123            if (maxI == 1) mImagesSavedTextView.setText("Image Saved");
124            else {
125                mImagesSavedTextView.setText("" + maxI + " Images Saved");
126            }
127        }
128        for (int i = 0; i < maxI; i++) {
129            bitmap = ((BitmapDrawable)mImages.get(i).getDrawable()).getBitmap();
130            mImages.get(i).setImageDrawable(res);
131            MediaStore.Images.Media.insertImage(getContentResolver(), bitmap,
132                    sdf.format(cal.getTime()) + "_image" + i + ".jpg", "image " + i);
133        }
134        mStartStopButton.setText("Start");
135        count = -1;
136        countHasReachedMax = false;
137        mSpinner.setEnabled(true);
138        mHandler.postDelayed(new Runnable() {
139            public void run() {
140                clearImagesSavedTextView();
141            }
142        }, 5000);
143    }
144
145    @Override
146    public void onCreate(Bundle savedInstanceState) {
147        super.onCreate(savedInstanceState);
148        setContentView(R.layout.simplecamera);
149        setTitle("Smart Camera");
150
151        mContext = new MffContext(this);
152
153        mCameraView = (SurfaceView) findViewById(R.id.cameraView);
154        mGoodBadTextView = (TextView) findViewById(R.id.goodOrBadTextView);
155        mFPSTextView = (TextView) findViewById(R.id.fpsTextView);
156        mScoreTextView = (TextView) findViewById(R.id.scoreTextView);
157        mStartStopButton = (Button) findViewById(R.id.startButton);
158        mImagesSavedTextView = (TextView) findViewById(R.id.imagesSavedTextView);
159        mImagesSavedTextView.setText("");
160        mSpinner = (Spinner) findViewById(R.id.spinner);
161        mLinearLayout = (LinearLayout) findViewById(R.id.scrollViewLinearLayout);
162        mImages = new ArrayList<ImageView>();
163
164        // Spinner is used to determine how many image views are displayed at the bottom
165        // of the screen. Based on the item position that is selected, we inflate that
166        // many imageviews into the bottom linear layout.
167        mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
168            @Override
169            public void onItemSelected(AdapterView<?> parentView, View selectedItemView,
170                    int position, long id) {
171                mLinearLayout.removeViews(0,numImages);
172                numImages = position+1;
173                mImages.clear();
174                LayoutInflater inflater = getLayoutInflater();
175                for (int i = 0; i < numImages; i++) {
176                    ImageView tmp = (ImageView) inflater.inflate(R.layout.imageview, null);
177                    mImages.add(tmp);
178                    mLinearLayout.addView(tmp);
179                }
180            }
181
182            @Override
183            public void onNothingSelected(AdapterView<?> parentView) {
184            }
185        });
186
187        numImages = mSpinner.getSelectedItemPosition()+1;
188        mImages.clear();
189        LayoutInflater inflater = getLayoutInflater();
190        for (int i = 0; i < numImages; i++) {
191            ImageView tmp = (ImageView) inflater.inflate(R.layout.imageview, null);
192            mImages.add(tmp);
193            mLinearLayout.addView(tmp);
194
195        }
196
197        // Button used to start and stop the capture of images when they are deemed great
198        mStartStopButton.setOnClickListener(new OnClickListener() {
199            @Override
200            public void onClick(View v) {
201                if (mStartStopButton.getText().equals("Start")) {
202                    mGraph.getVariable("startCapture").setValue(true);
203                    mStartStopButton.setText("Stop");
204                    mSpinner.setEnabled(false);
205                } else {
206                    boolean tmp = (Boolean) mGraph.getVariable("startCapture").getValue();
207                    if (tmp == false) {
208                        return;
209                    }
210                    if (count == numImages-1) countHasReachedMax = true;
211                    captureImages();
212                }
213            }
214        });
215
216        // Button to open the gallery to show the images in there
217        Button galleryOpen = (Button) findViewById(R.id.galleryOpenButton);
218        galleryOpen.setOnClickListener(new OnClickListener() {
219           @Override
220           public void onClick(View v) {
221               Intent openGalleryIntent = new Intent(Intent.ACTION_MAIN);
222               openGalleryIntent.addCategory(Intent.CATEGORY_APP_GALLERY);
223               startActivity(openGalleryIntent);
224           }
225        });
226
227        loadGraph();
228        mGraph.getVariable("startCapture").setValue(false);
229        runGraph();
230    }
231
232    @Override
233    public void onPause() {
234        super.onPause();
235        Log.i(TAG, "onPause");
236        if (mContext != null) {
237            mContext.onPause();
238        }
239    }
240
241    @Override
242    public void onResume() {
243        super.onResume();
244        Log.i(TAG, "onResume");
245        if (mContext != null) {
246            mContext.onResume();
247        }
248        if (isPendingRunGraph) {
249            isPendingRunGraph = false;
250            runGraph();
251        }
252    }
253
254    @Override
255    public void onStop() {
256        super.onStop();
257        Log.i(TAG, "onStop");
258    }
259
260    // Build the Filtergraph for Camera
261    private void loadGraph() {
262        try {
263            mGraph = GraphReader.readXmlGraphResource(mContext, R.raw.camera_graph);
264            mRunner = mGraph.getRunner();
265
266            // Connect views
267            mGraph.bindFilterToView("camViewTarget", mCameraView);
268            mGraph.bindFilterToView("goodOrBadTextView", mGoodBadTextView);
269            mGraph.bindFilterToView("fpsTextView", mFPSTextView);
270            mGraph.bindFilterToView("scoreTextView", mScoreTextView);
271
272            // Used for Facial Expressions
273            if (sUseFacialExpression) {
274                mGraph.bindFilterToView("eyesTextView", mEyesTextView);
275                mGraph.bindFilterToView("smilesTextView", mSmilesTextView);
276            }
277
278        } catch (IOException e) {
279            e.printStackTrace();
280        }
281    }
282
283    // Asynchronously run the filtergraph
284    private void runGraph() {
285        mRunner.setIsVerbose(true);
286        mRunner.start(mGraph);
287    }
288}
289