package com.performanceactive.plugins.camera; import android.app.Activity; import android.content.Intent; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; import android.graphics.BitmapFactory; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Point; import android.hardware.Camera; import android.hardware.Camera.AutoFocusCallback; import android.hardware.Camera.PictureCallback; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup.LayoutParams; import android.view.Window; import android.view.WindowManager; import android.widget.FrameLayout; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.ImageView.ScaleType; import android.widget.RelativeLayout; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.util.List; import static android.hardware.Camera.Parameters.FLASH_MODE_OFF; import static android.hardware.Camera.Parameters.FOCUS_MODE_AUTO; import static android.hardware.Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE; public class CustomCameraActivity extends Activity { private static final String TAG = CustomCameraActivity.class.getSimpleName(); private static final float ASPECT_RATIO = 126.0f / 86; public static String FILENAME = "Filename"; public static String QUALITY = "Quality"; public static String TARGET_WIDTH = "TargetWidth"; public static String TARGET_HEIGHT = "TargetHeight"; public static String IMAGE_URI = "ImageUri"; public static String ERROR_MESSAGE = "ErrorMessage"; public static int RESULT_ERROR = 2; private Camera camera; private RelativeLayout layout; private FrameLayout cameraPreviewView; private ImageView borderTopLeft; private ImageView borderTopRight; private ImageView borderBottomLeft; private ImageView borderBottomRight; private ImageButton captureButton; @Override protected void onResume() { super.onResume(); try { camera = Camera.open(); configureCamera(); displayCameraPreview(); } catch (Exception e) { finishWithError("Camera is not accessible"); } } private void configureCamera() { Camera.Parameters cameraSettings = camera.getParameters(); cameraSettings.setJpegQuality(100); List<String> supportedFocusModes = cameraSettings.getSupportedFocusModes(); if (supportedFocusModes.contains(FOCUS_MODE_CONTINUOUS_PICTURE)) { cameraSettings.setFocusMode(FOCUS_MODE_CONTINUOUS_PICTURE); } else if (supportedFocusModes.contains(FOCUS_MODE_AUTO)) { cameraSettings.setFocusMode(FOCUS_MODE_AUTO); } cameraSettings.setFlashMode(FLASH_MODE_OFF); camera.setParameters(cameraSettings); } private void displayCameraPreview() { cameraPreviewView.removeAllViews(); cameraPreviewView.addView(new CustomCameraPreview(this, camera)); } @Override protected void onPause() { super.onPause(); releaseCamera(); } private void releaseCamera() { if (camera != null) { camera.stopPreview(); camera.release(); } } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); requestWindowFeature(Window.FEATURE_NO_TITLE); layout = new RelativeLayout(this); RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); layout.setLayoutParams(layoutParams); createCameraPreview(); createTopLeftBorder(); createTopRightBorder(); createBottomLeftBorder(); createBottomRightBorder(); layoutBottomBorderImagesRespectingAspectRatio(); createCaptureButton(); setContentView(layout); } private void createCameraPreview() { cameraPreviewView = new FrameLayout(this); FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); cameraPreviewView.setLayoutParams(layoutParams); layout.addView(cameraPreviewView); } private void createTopLeftBorder() { borderTopLeft = new ImageView(this); setBitmap(borderTopLeft, "border_top_left.png"); RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(dpToPixels(50), dpToPixels(50)); layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP); layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT); if (isXLargeScreen()) { layoutParams.topMargin = dpToPixels(100); layoutParams.leftMargin = dpToPixels(100); } else if (isLargeScreen()) { layoutParams.topMargin = dpToPixels(50); layoutParams.leftMargin = dpToPixels(50); } else { layoutParams.topMargin = dpToPixels(10); layoutParams.leftMargin = dpToPixels(10); } borderTopLeft.setLayoutParams(layoutParams); layout.addView(borderTopLeft); } private void createTopRightBorder() { borderTopRight = new ImageView(this); setBitmap(borderTopRight, "border_top_right.png"); RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(dpToPixels(50), dpToPixels(50)); layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP); layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); if (isXLargeScreen()) { layoutParams.topMargin = dpToPixels(100); layoutParams.rightMargin = dpToPixels(100); } else if (isLargeScreen()) { layoutParams.topMargin = dpToPixels(50); layoutParams.rightMargin = dpToPixels(50); } else { layoutParams.topMargin = dpToPixels(10); layoutParams.rightMargin = dpToPixels(10); } borderTopRight.setLayoutParams(layoutParams); layout.addView(borderTopRight); } private void createBottomLeftBorder() { borderBottomLeft = new ImageView(this); setBitmap(borderBottomLeft, "border_bottom_left.png"); RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(dpToPixels(50), dpToPixels(50)); layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT); if (isXLargeScreen()) { layoutParams.leftMargin = dpToPixels(100); } else if (isLargeScreen()) { layoutParams.leftMargin = dpToPixels(50); } else { layoutParams.leftMargin = dpToPixels(10); } borderBottomLeft.setLayoutParams(layoutParams); layout.addView(borderBottomLeft); } private void createBottomRightBorder() { borderBottomRight = new ImageView(this); setBitmap(borderBottomRight, "border_bottom_right.png"); RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(dpToPixels(50), dpToPixels(50)); layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); if (isXLargeScreen()) { layoutParams.rightMargin = dpToPixels(100); } else if (isLargeScreen()) { layoutParams.rightMargin = dpToPixels(50); } else { layoutParams.rightMargin = dpToPixels(10); } borderBottomRight.setLayoutParams(layoutParams); layout.addView(borderBottomRight); } private void layoutBottomBorderImagesRespectingAspectRatio() { RelativeLayout.LayoutParams borderTopLeftLayoutParams = (RelativeLayout.LayoutParams)borderTopLeft.getLayoutParams(); RelativeLayout.LayoutParams borderTopRightLayoutParams = (RelativeLayout.LayoutParams)borderTopRight.getLayoutParams(); RelativeLayout.LayoutParams borderBottomLeftLayoutParams = (RelativeLayout.LayoutParams)borderBottomLeft.getLayoutParams(); RelativeLayout.LayoutParams borderBottomRightLayoutParams = (RelativeLayout.LayoutParams)borderBottomRight.getLayoutParams(); float height = (screenWidthInPixels() - borderTopRightLayoutParams.rightMargin - borderTopLeftLayoutParams.leftMargin) * ASPECT_RATIO; borderBottomLeftLayoutParams.bottomMargin = screenHeightInPixels() - Math.round(height) - borderTopLeftLayoutParams.topMargin; borderBottomLeft.setLayoutParams(borderBottomLeftLayoutParams); borderBottomRightLayoutParams.bottomMargin = screenHeightInPixels() - Math.round(height) - borderTopRightLayoutParams.topMargin; borderBottomRight.setLayoutParams(borderBottomRightLayoutParams); } private int screenWidthInPixels() { Point size = new Point(); getWindowManager().getDefaultDisplay().getSize(size); return size.x; } private int screenHeightInPixels() { Point size = new Point(); getWindowManager().getDefaultDisplay().getSize(size); return size.y; } private void createCaptureButton() { captureButton = new ImageButton(getApplicationContext()); setBitmap(captureButton, "capture_button.png"); captureButton.setBackgroundColor(Color.TRANSPARENT); captureButton.setScaleType(ScaleType.FIT_CENTER); RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(dpToPixels(75), dpToPixels(75)); layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); layoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL); layoutParams.bottomMargin = dpToPixels(10); captureButton.setLayoutParams(layoutParams); captureButton.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { setCaptureButtonImageForEvent(event); return false; } }); captureButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { takePictureWithAutoFocus(); } }); layout.addView(captureButton); } private void setCaptureButtonImageForEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { setBitmap(captureButton, "capture_button_pressed.png"); } else if (event.getAction() == MotionEvent.ACTION_UP) { setBitmap(captureButton, "capture_button.png"); } } private void takePictureWithAutoFocus() { if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_AUTOFOCUS)) { camera.autoFocus(new AutoFocusCallback() { @Override public void onAutoFocus(boolean success, Camera camera) { takePicture(); } }); } else { takePicture(); } } private void takePicture() { try { camera.takePicture(null, null, new PictureCallback() { @Override public void onPictureTaken(byte[] jpegData, Camera camera) { new OutputCapturedImageTask().execute(jpegData); } }); } catch (Exception e) { finishWithError("Failed to take image"); } } private class OutputCapturedImageTask extends AsyncTask<byte[], Void, Void> { @Override protected Void doInBackground(byte[]... jpegData) { try { String filename = getIntent().getStringExtra(FILENAME); int quality = getIntent().getIntExtra(QUALITY, 80); File capturedImageFile = new File(getCacheDir(), filename); Bitmap capturedImage = getScaledBitmap(jpegData[0]); capturedImage = correctCaptureImageOrientation(capturedImage); capturedImage.compress(CompressFormat.JPEG, quality, new FileOutputStream(capturedImageFile)); Intent data = new Intent(); data.putExtra(IMAGE_URI, Uri.fromFile(capturedImageFile).toString()); setResult(RESULT_OK, data); finish(); } catch (Exception e) { finishWithError("Failed to save image"); } return null; } } private Bitmap getScaledBitmap(byte[] jpegData) { int targetWidth = getIntent().getIntExtra(TARGET_WIDTH, -1); int targetHeight = getIntent().getIntExtra(TARGET_HEIGHT, -1); if (targetWidth <= 0 && targetHeight <= 0) { return BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length); } // get dimensions of image without scaling BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length, options); // decode image as close to requested scale as possible options.inJustDecodeBounds = false; options.inSampleSize = calculateInSampleSize(options, targetWidth, targetHeight); Bitmap bitmap = BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length, options); // set missing width/height based on aspect ratio float aspectRatio = ((float)options.outHeight) / options.outWidth; if (targetWidth > 0 && targetHeight <= 0) { targetHeight = Math.round(targetWidth * aspectRatio); } else if (targetWidth <= 0 && targetHeight > 0) { targetWidth = Math.round(targetHeight / aspectRatio); } // make sure we also Matrix matrix = new Matrix(); matrix.postRotate(90); return Bitmap.createScaledBitmap(bitmap, targetWidth, targetHeight, true); } private int calculateInSampleSize(BitmapFactory.Options options, int requestedWidth, int requestedHeight) { int originalHeight = options.outHeight; int originalWidth = options.outWidth; int inSampleSize = 1; if (originalHeight > requestedHeight || originalWidth > requestedWidth) { int halfHeight = originalHeight / 2; int halfWidth = originalWidth / 2; while ((halfHeight / inSampleSize) > requestedHeight && (halfWidth / inSampleSize) > requestedWidth) { inSampleSize *= 2; } } return inSampleSize; } private Bitmap correctCaptureImageOrientation(Bitmap bitmap) { Matrix matrix = new Matrix(); matrix.postRotate(90); return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); } private void finishWithError(String message) { Intent data = new Intent().putExtra(ERROR_MESSAGE, message); setResult(RESULT_ERROR, data); finish(); } private int dpToPixels(int dp) { float density = getResources().getDisplayMetrics().density; return Math.round(dp * density); } private boolean isXLargeScreen() { int screenLayout = getResources().getConfiguration().screenLayout; return (screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE; } private boolean isLargeScreen() { int screenLayout = getResources().getConfiguration().screenLayout; return (screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_LARGE; } private void setBitmap(ImageView imageView, String imageName) { try { InputStream imageStream = getAssets().open("www/img/cameraoverlay/" + imageName); Bitmap bitmap = BitmapFactory.decodeStream(imageStream); imageView.setImageBitmap(bitmap); imageStream.close(); } catch (Exception e) { Log.e(TAG, "Could load image", e); } } }