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 17 package androidx.media.filterfw.samples.simplecamera; 18 19 import android.app.Activity; 20 import android.content.Intent; 21 import android.graphics.Bitmap; 22 import android.graphics.drawable.BitmapDrawable; 23 import android.graphics.drawable.Drawable; 24 import android.os.Bundle; 25 import android.os.Handler; 26 import android.provider.MediaStore; 27 import android.util.Log; 28 import android.view.LayoutInflater; 29 import android.view.SurfaceView; 30 import android.view.View; 31 import android.view.View.OnClickListener; 32 import android.widget.AdapterView; 33 import android.widget.Button; 34 import android.widget.ImageView; 35 import android.widget.LinearLayout; 36 import android.widget.Spinner; 37 import android.widget.TextView; 38 import androidx.media.filterfw.FilterGraph; 39 import androidx.media.filterfw.GraphReader; 40 import androidx.media.filterfw.GraphRunner; 41 import androidx.media.filterfw.MffContext; 42 43 import java.io.IOException; 44 import java.text.SimpleDateFormat; 45 import java.util.ArrayList; 46 import java.util.Calendar; 47 48 49 public 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 getImageView()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 runGraphOnImage(String filePath, String fileName)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 clearImagesSavedTextView()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 captureImages()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 onCreate(Bundle savedInstanceState)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 onPause()233 public void onPause() { 234 super.onPause(); 235 Log.i(TAG, "onPause"); 236 if (mContext != null) { 237 mContext.onPause(); 238 } 239 } 240 241 @Override onResume()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 onStop()255 public void onStop() { 256 super.onStop(); 257 Log.i(TAG, "onStop"); 258 } 259 260 // Build the Filtergraph for Camera loadGraph()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 runGraph()284 private void runGraph() { 285 mRunner.setIsVerbose(true); 286 mRunner.start(mGraph); 287 } 288 } 289