package fyp.hkust.facet.skincolordetection; import android.Manifest; import android.annotation.TargetApi; import android.app.Activity; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Point; import android.graphics.Typeface; import android.graphics.drawable.ColorDrawable; import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.support.v4.app.ActivityCompat; import android.support.v4.app.NotificationCompat; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.text.Spannable; import android.text.SpannableString; import android.text.style.TypefaceSpan; import android.util.DisplayMetrics; import android.util.Log; import android.view.Display; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; import com.nhaarman.supertooltips.ToolTip; import com.nhaarman.supertooltips.ToolTipRelativeLayout; import com.nhaarman.supertooltips.ToolTipView; import com.taishi.flipprogressdialog.FlipProgressDialog; import org.opencv.android.BaseLoaderCallback; import org.opencv.android.LoaderCallbackInterface; import org.opencv.android.OpenCVLoader; import org.opencv.core.CvType; import org.opencv.core.Mat; import org.opencv.core.Scalar; import org.opencv.imgproc.Imgproc; import java.io.File; import java.io.FileOutputStream; import java.util.ArrayList; import java.util.List; import java.util.Random; import fyp.hkust.facet.R; import fyp.hkust.facet.activity.MainMenuActivity; import fyp.hkust.facet.util.FontManager; import fyp.hkust.facet.whiteBalance.algorithms.grayWorld.GrayWorld; import fyp.hkust.facet.whiteBalance.algorithms.histogramStretching.HistogramStretching; import fyp.hkust.facet.whiteBalance.algorithms.improvedWP.ImprovedWP; import id.zelory.compressor.Compressor; import me.shaohui.advancedluban.Luban; import static android.support.v4.app.NotificationCompat.PRIORITY_HIGH; public class CaptureActivity extends AppCompatActivity implements View.OnClickListener, ToolTipView.OnToolTipViewClickedListener { private static final String TAG = CaptureActivity.class.getSimpleName(); private Context instance; private Filter filter; private String imagePath; private TextView colorresult; private Mat demo; private ImageView mImgResult; private ProgressBar waitingCircle; private Intent intent; private ImageButton[] imageButtons; private TextView[] textViews; private String comeFromActivity; private Bitmap originalBitmap; private Bitmap compressedBitmap; private int scaledHeight = 0; private int scaledWidth = 0; private int taskCounter; private int photoQuality = 15; private int selectPhoto = 0; private Bitmap scaledBitmap; // add this number to count their finished order private ArrayList<Bitmap> convertedBitmaps; private float mRelativeFaceSize = 0.2f; private int mAbsoluteFaceSize = 0; private ArrayList<Integer> convertNumber; private ToolTipView mBlueToolTipView; private ToolTipRelativeLayout toolTipRelativeLayout; private int n; // private GifLoadingView mView; private Handler handler; // declared before onCreate private Runnable myRunnable; private static final int REQUEST_EXTERNAL_STORAGE = 1; private static String[] PERMISSIONS_STORAGE = { Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE }; private FlipProgressDialog fpd; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_capture); getSupportActionBar().setHomeButtonEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setBackgroundDrawable(new ColorDrawable(getResources().getColor(R.color.black))); SpannableString s = new SpannableString(getResources().getString(R.string.app_name)); s.setSpan(new TypefaceSpan(FontManager.APP_FONT), 0, s.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); getSupportActionBar().setTitle(s); Typeface fontType = FontManager.getTypeface(getApplicationContext(), FontManager.APP_FONT); FontManager.markAsIconContainer(findViewById(R.id.activity_capture_layout), fontType); verifyStoragePermissions(this); intent = this.getIntent(); String path = intent.getStringExtra("path"); if (intent.getStringExtra("activity") != null) { comeFromActivity = intent.getStringExtra("activity"); photoQuality = 65; } else { comeFromActivity = "Other"; } // String color = intent.getStringExtra("color"); imageButtons = new ImageButton[]{ (ImageButton) findViewById(R.id.original_image), (ImageButton) findViewById(R.id.converted_image1), (ImageButton) findViewById(R.id.converted_image2), (ImageButton) findViewById(R.id.converted_image3), }; textViews = new TextView[]{ (TextView) findViewById(R.id.original_image_text), (TextView) findViewById(R.id.converted_image1_text), (TextView) findViewById(R.id.converted_image2_text), (TextView) findViewById(R.id.converted_image3_text), }; mImgResult = (ImageView) findViewById(R.id.image_show); waitingCircle = (ProgressBar) findViewById(R.id.progressBar); //pop up hint toolTipRelativeLayout = (ToolTipRelativeLayout) findViewById(R.id.capture_activity_tooltipRelativeLayout); findViewById(R.id.capture_activity_redtv).setOnClickListener(this); new Handler().postDelayed(new Runnable() { @Override public void run() { addBlueToolTipView(); } }, 1100); //end of hint File f = new File(path); // originalBitmap = BitmapFactory.decodeFile(f.getAbsolutePath()); Luban.compress(getApplicationContext(), f) .putGear(Luban.CUSTOM_GEAR) .asObservable() // generate Observable .subscribe(); // subscribe the compress result Display display = getWindowManager().getDefaultDisplay(); Point size = new Point(); display.getSize(size); float width = size.x * 0.7f; float height = size.y * 0.6f; mImgResult.setPadding((int) (size.x * 0.15), (int) (size.y * 0.05), (int) (size.x * 0.15), (int) (size.y * 0.05)); if (comeFromActivity.equals("ShowCameraViewActivity")) { width = size.x * 0.8f; height = size.y * 0.8f; mImgResult.setPadding((int) (size.x * 0.10), (int) (size.y * 0.1), (int) (size.x * 0.10), (int) (size.y * 0.1)); } Log.d(TAG, " device_size:" + width + " : " + height); compressedBitmap = new Compressor.Builder(CaptureActivity.this) .setMaxWidth(width) .setMaxHeight(height) .setQuality(photoQuality) .setCompressFormat(Bitmap.CompressFormat.WEBP) .setDestinationDirectoryPath(Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES).getAbsolutePath()) .build() .compressToBitmap(f); compressedBitmap = RotateBitmap(compressedBitmap, -90, comeFromActivity); // changeDimensions(); //scaledBitmap = createScaledBitmap(originalBitmap, scaledWidth, scaledHeight, false); //Log.d("path", path); taskCounter = 0; Random rand = new Random(); n = rand.nextInt(7) + 1; //12 is the maximum and the 1 is our minimum try { /*recycling unused objects in order to make the memory they currently occupy available for quick reuse.*/ System.gc(); fpd = new FlipProgressDialog(); List<Integer> imageList = new ArrayList<Integer>(); imageList.add(R.drawable.app_icon_100); fpd.setImageList(imageList); // *Set a imageList* [Have to. Transparent background png recommended] fpd.setCanceledOnTouchOutside(false);// If true, the dialog will be dismissed when user touch outside of the dialog. If false, the dialog won't be dismissed. fpd.setImageMargin(10); fpd.setMinAlpha(1.0f); // Set an alpha when flipping ratation start and end fpd.setMaxAlpha(1.0f); fpd.setDimAmount(80.0f); fpd.setOrientation("rotationY"); // Set a flipping rotation fpd.setDuration(1500); fpd.setImageSize(170); fpd.setStartAngle(0.0f); // Set an angle when flipping ratation start fpd.setEndAngle(360.0f); fpd.setBackgroundColor(Color.parseColor("#3b393d")); // Set a background color of dialog fpd.setBackgroundAlpha(0.8f); fpd.setCornerRadius(10); fpd.show(getFragmentManager(), "Loading ..."); // int id = getResources().getIdentifier("num" + n, "drawable", getPackageName()); // mView = new GifLoadingView(); // mView.setBackgroundResource(id); // mView.show(getFragmentManager(), ""); // mView.setCancelable(false); // mView.setDimming(true); // mView.setRadius(1); final MyTask myTask1 = new MyTask(this, 1); myTask1.execute(); final MyTask myTask2 = new MyTask(this, 2); StartAsyncTaskInParallel(myTask2); final MyTask myTask3 = new MyTask(this, 3); StartAsyncTaskInParallel(myTask3); } catch (Exception obj) { } // initThreads(); // colorresult.setText(color); imageButtons[0].setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { mImgResult.setImageBitmap(compressedBitmap); selectEffect(imageButtons[0], textViews[0]); selectPhoto = 0; } }); imageButtons[1].setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { mImgResult.setImageBitmap(convertedBitmaps.get(0)); selectEffect(imageButtons[1], textViews[1]); selectPhoto = 1; mBlueToolTipView.setVisibility(View.GONE); toolTipRelativeLayout.setVisibility(View.GONE); } }); imageButtons[2].setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { mImgResult.setImageBitmap(convertedBitmaps.get(1)); selectEffect(imageButtons[2], textViews[2]); selectPhoto = 2; } }); imageButtons[3].setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { mImgResult.setImageBitmap(convertedBitmaps.get(2)); selectEffect(imageButtons[3], textViews[3]); selectPhoto = 3; } }); } public static void verifyStoragePermissions(Activity activity) { // Check if we have write permission int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE); if (permission != PackageManager.PERMISSION_GRANTED) { // We don't have permission so prompt the user ActivityCompat.requestPermissions( activity, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE ); } } private void selectEffect(ImageButton selectButton, TextView selectText) { for (int i = 0; i < 4; i++) { imageButtons[i].setElevation(0.0f); textViews[i].setElevation(0.0f); textViews[i].setTypeface(null, Typeface.NORMAL); textViews[i].setTextSize(12.0f); } selectButton.setElevation(20.0f); selectText.setElevation(20.0f); selectText.setTypeface(null, Typeface.BOLD); selectText.setTextSize(18.0f); } //adding the hints @Override public void onToolTipViewClicked(ToolTipView toolTipView) { if (mBlueToolTipView == toolTipView) { mBlueToolTipView = null; } } @Override public void onClick(View v) { int id = v.getId(); if (id == R.id.capture_activity_redtv) { if (mBlueToolTipView == null) { addBlueToolTipView(); } else { mBlueToolTipView.remove(); mBlueToolTipView = null; } } } private void addBlueToolTipView() { ToolTip toolTip = new ToolTip() .withText("Select a suitable white balance and click right top button") .withColor(getResources().getColor(R.color.colorPrimary)) .withAnimationType(ToolTip.AnimationType.FROM_MASTER_VIEW); mBlueToolTipView = toolTipRelativeLayout.showToolTipForView(toolTip, findViewById(R.id.capture_activity_redtv)); mBlueToolTipView.setOnToolTipViewClickedListener(this); } //end of the hint private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) { @Override public void onManagerConnected(int status) { switch (status) { case LoaderCallbackInterface.SUCCESS: { Log.i("OpenCV", "OpenCV loaded successfully"); demo = new Mat(); } break; default: { super.onManagerConnected(status); } break; } } }; public void onResume() { super.onResume(); if (!OpenCVLoader.initDebug()) { Log.d("OpenCV", "Internal OpenCV library not found. Using OpenCV Manager for initialization"); OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_1_0, this, mLoaderCallback); } else { Log.d("OpenCV", "OpenCV library found inside package. Using it!"); mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS); } } @Override public void onPause() { super.onPause(); } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.whitebalance_menu, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: // app icon in action bar clicked; go home Intent intent = new Intent(this, MainMenuActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(intent); return true; case R.id.apply_btn: AlertDialog.Builder builder = new AlertDialog.Builder(CaptureActivity.this, R.style.Theme_AppCompat_Light_Dialog_Alert); builder.setTitle("Are you sure?"); if (selectPhoto == 0) { builder.setMessage("Original photo is the most suitable?"); } else { builder.setMessage("Effect " + selectPhoto + " is the most suitable?"); } builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { saveImageAndIntent(); // Toast.makeText(getApplicationContext(), "您按下OK按鈕", Toast.LENGTH_SHORT).show(); } }); //設定Negative按鈕資料 builder.setNegativeButton("No", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { //按下按鈕時顯示快顯 // Toast.makeText(getApplicationContext(), "您按下No按鈕", Toast.LENGTH_SHORT).show(); } }); builder.show(); return true; default: return super.onOptionsItemSelected(item); } } public void saveImageAndIntent() { try { //Write file String filename = "bitmap.png"; FileOutputStream stream = this.openFileOutput(filename, Context.MODE_PRIVATE); convertedBitmaps.get(selectPhoto).compress(Bitmap.CompressFormat.PNG, 100, stream); //Cleanup stream.close(); convertedBitmaps.get(selectPhoto).recycle(); //Pop intent Intent colorDectectionIntent = new Intent(this, ColorDetectionActivity.class); colorDectectionIntent.putExtra("image", filename); startActivity(colorDectectionIntent); } catch (Exception e) { e.printStackTrace(); } } public static Bitmap RotateBitmap(Bitmap source, float angle, String check) { Log.d(TAG + "activity compare: ", check + " : " + "ShowCameraViewActivity"); Matrix matrix = new Matrix(); //rotate if the phone come from taking photo if (check.equals("ShowCameraViewActivity")) { matrix.postRotate(angle); } return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true); } private class MyTask extends AsyncTask<String, Integer, Integer> { int number; private String content = null; private boolean error = false; Context mContext; int NOTIFICATION_ID = 1; Notification mNotification; NotificationManager mNotificationManager; public MyTask(Context context, int target) { this.mContext = context; number = target; //Get the notification manager mNotificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); } private void createNotification(Context context, String message) { Intent notificationIntent = new Intent(context, CaptureActivity.class); notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); PendingIntent intent = PendingIntent.getActivity(context, 0, notificationIntent, 0); NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context) .setSmallIcon(R.mipmap.app_icon) .setContentTitle(context.getString(R.string.app_name)) .setContentIntent(intent) .setPriority(PRIORITY_HIGH) //private static final PRIORITY_HIGH = 5; .setContentText(message) .setAutoCancel(true); NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); mNotificationManager.notify(0, mBuilder.build()); } @Override protected Integer doInBackground(String... param) { try { convertedBitmaps = new ArrayList<Bitmap>(5); if (!convertedBitmaps.contains(compressedBitmap)) { convertedBitmaps.add(compressedBitmap); } switch (number) { case 1: GrayWorld grayWorld = new GrayWorld(compressedBitmap); convertedBitmaps.add(grayWorld.getConvertedBitmap()); break; case 2: HistogramStretching histogramStretching = new HistogramStretching(compressedBitmap); convertedBitmaps.add(histogramStretching.getConvertedBitmap()); break; case 3: ImprovedWP improvedWP = new ImprovedWP(compressedBitmap); convertedBitmaps.add(improvedWP.getConvertedBitmap()); break; } Log.d("Finish Task", ""); taskCounter++; } catch (Exception e) { Log.w("HTTP4:", e); content = e.getMessage(); error = true; cancel(true); } // convertedBitmaps = new Bitmap[] { // scaledBitmap, // histogramStretching.getConvertedBitmap(), // grayWorld.getConvertedBitmap(), // improvedWP.getConvertedBitmap() // }; return null; } @Override protected void onPostExecute(Integer result) { super.onPostExecute(result); if (error) { createNotification(CaptureActivity.this, "Image Processing ended abnormally!"); } else { Log.d("taskcounter :", taskCounter + ""); mImgResult.setImageBitmap(compressedBitmap); imageButtons[0].setImageBitmap(compressedBitmap); selectEffect(imageButtons[0], textViews[0]); switch (number) { case 1: imageButtons[3].setImageBitmap(convertedBitmaps.get(taskCounter - 1)); // mView.dismiss(); // convertNumber.add(taskCounter-1); break; case 2: imageButtons[2].setImageBitmap(convertedBitmaps.get(taskCounter - 1)); fpd.dismiss(); // convertNumber.add(taskCounter-1); break; case 3: imageButtons[1].setImageBitmap(convertedBitmaps.get(taskCounter - 1)); // convertNumber.add(taskCounter-1); break; } // createNotification(CaptureActivity.this, "Image processing is complete!"); // Toast.makeText(mContext, "Image processing is complete!", Toast.LENGTH_SHORT).show(); } // demo= new Mat(); // Utils.bitmapToMat(convertedBitmaps[1],demo); // Mat gray_demo = new Mat(); // Imgproc.cvtColor(demo, gray_demo, Imgproc.COLOR_RGB2GRAY); } @Override protected void onCancelled() { super.onCancelled(); } @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); } @Override protected void onPreExecute() { super.onPreExecute(); createNotification(CaptureActivity.this, "Image is in progress"); } } @TargetApi(Build.VERSION_CODES.HONEYCOMB) private void StartAsyncTaskInParallel(MyTask task) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); else task.execute(); } private Scalar converScalarHsv2Rgba(Scalar hsvColor) { Mat pointMatRgba = new Mat(); Mat pointMatHsv = new Mat(1, 1, CvType.CV_8UC3, hsvColor); Imgproc.cvtColor(pointMatHsv, pointMatRgba, Imgproc.COLOR_HSV2RGB_FULL, 4); return new Scalar(pointMatRgba.get(0, 0)); } private void setMinFaceSize(float faceSize) { mRelativeFaceSize = faceSize; mAbsoluteFaceSize = 0; } public void changeDimensions() { // dimensions of display Display display = getWindowManager().getDefaultDisplay(); Point size = new Point(); display.getSize(size); int widthDisplay = size.x; int heightDisplay = size.y; int widthDisplayDp = pxToDp(widthDisplay); int heightDisplayDp = pxToDp(heightDisplay); Log.i(TAG, "display width in px: " + Integer.toString(widthDisplay)); Log.i(TAG, "display height in px: " + Integer.toString(heightDisplay)); Log.i(TAG, "display width in dp: " + Integer.toString(widthDisplayDp)); Log.i(TAG, "display height in dp: " + Integer.toString(heightDisplayDp)); int widthImage = compressedBitmap.getWidth(); int widthImageDp = pxToDp(widthImage); int heightImage = compressedBitmap.getHeight(); int heightImageDp = pxToDp(heightImage); Log.i(TAG, "bitmap width in px: " + Integer.toString(widthImage)); Log.i(TAG, "bitmap height in px: " + Integer.toString(heightImage)); Log.i(TAG, "bitmap width in dp: " + Integer.toString(widthImageDp)); Log.i(TAG, "bitmap height in dp: " + Integer.toString(heightImageDp)); if (heightDisplay - 300 >= heightImage && widthDisplay >= widthImage) { scaledHeight = heightImage; scaledWidth = widthImage; } else { scaledHeight = heightDisplay - 300; double ratio = (double) scaledHeight / (double) heightImage; scaledWidth = (int) ((double) widthImage * ratio); } Log.i(TAG, "scaled width: " + Integer.toString(scaledWidth)); Log.i(TAG, "scaled height: " + Integer.toString(scaledHeight)); } public int pxToDp(int px) { DisplayMetrics displayMetrics = getApplicationContext().getResources().getDisplayMetrics(); int dp = Math.round(px / (displayMetrics.ydpi / DisplayMetrics.DENSITY_DEFAULT)); return dp; } }