mirror of
https://gitee.com/shuto/customCamera.git
synced 2026-05-02 00:07:24 +08:00
Improve the plugin to try/catch outofmemory when we try to rotate or compress a picture.
This commit is contained in:
@@ -7,18 +7,10 @@ import android.util.Base64;
|
||||
|
||||
import org.apache.cordova.CallbackContext;
|
||||
import org.apache.cordova.CordovaPlugin;
|
||||
import org.apache.cordova.PluginResult;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.IOException;
|
||||
|
||||
public class CameraLauncher extends CordovaPlugin {
|
||||
|
||||
protected CallbackContext callbackContext;
|
||||
@@ -57,7 +49,8 @@ public class CameraLauncher extends CordovaPlugin {
|
||||
|
||||
return false;
|
||||
}
|
||||
TransferBigData.setImgBackgroundBase64(imgBackgroundBase64);
|
||||
TmpFileUtils.createTmpFile(this.cordova.getActivity(), CameraActivity.NAME_FILE_BACKGROUND, imgBackgroundBase64);
|
||||
imgBackgroundBase64 = null;
|
||||
}
|
||||
|
||||
if (args.getString(1) != "null") {
|
||||
@@ -71,11 +64,12 @@ public class CameraLauncher extends CordovaPlugin {
|
||||
|
||||
return false;
|
||||
}
|
||||
TransferBigData.setImgBackgroundBase64OtherOrientation(imgBackgroundBase64OtherOrientation);
|
||||
TmpFileUtils.createTmpFile(this.cordova.getActivity(), CameraActivity.NAME_FILE_BACKGROUND_OTHER, imgBackgroundBase64OtherOrientation);
|
||||
imgBackgroundBase64OtherOrientation = null;
|
||||
}
|
||||
|
||||
// If we don't have a background image, disable miniature and opacity options.
|
||||
if (TransferBigData.getImgBackgroundBase64() == null) {
|
||||
if (args.getString(0) == "null") {
|
||||
intent.putExtra("miniature", false);
|
||||
intent.putExtra("opacity", false);
|
||||
} else {
|
||||
@@ -113,6 +107,9 @@ public class CameraLauncher extends CordovaPlugin {
|
||||
* @param intent Contains parameters of the activity.
|
||||
*/
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
|
||||
// remove temporary files.
|
||||
this.cordova.getActivity().deleteFile(CameraActivity.NAME_FILE_BACKGROUND);
|
||||
this.cordova.getActivity().deleteFile(CameraActivity.NAME_FILE_BACKGROUND_OTHER);
|
||||
if (requestCode == CameraLauncher.REQUEST_CODE) {
|
||||
switch (resultCode) {
|
||||
case CameraLauncher.RESULT_ERROR:
|
||||
@@ -125,9 +122,11 @@ public class CameraLauncher extends CordovaPlugin {
|
||||
break;
|
||||
case CameraLauncher.RESULT_SUCCESS:
|
||||
try {
|
||||
byte[] output = Base64.encode(TransferBigData.getImgTaken(),
|
||||
byte[] output = Base64.encode(TmpFileUtils.getTmpFileContent(this.cordova.getActivity(), CameraActivity.NAME_FILE_PICTURE_TAKEN),
|
||||
Base64.NO_WRAP);
|
||||
this.cordova.getActivity().deleteFile(CameraActivity.NAME_FILE_PICTURE_TAKEN);
|
||||
String jsOut = new String(output);
|
||||
output = null;
|
||||
|
||||
this.callbackContext.success(jsOut);
|
||||
} catch (Exception e) {
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/background"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:alpha="0.2"
|
||||
android:scaleType="fitXY" />
|
||||
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package org.geneanet.customcamera;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.BitmapFactory.Options;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.Display;
|
||||
|
||||
public class BitmapUtils {
|
||||
/**
|
||||
@@ -19,48 +22,49 @@ public class BitmapUtils {
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the best value of inSampleSize in the option object to adapt the picture at the screen size.
|
||||
*
|
||||
* @param Options options Option object to set inSampleSize.
|
||||
* @param int destWidth Width destination.
|
||||
* @param int destHeight Height destination.
|
||||
*/
|
||||
public static void determineInSampleSize(Options options, int destWidth, int destHeight) {
|
||||
// Raw height and width of image
|
||||
final int height = options.outHeight;
|
||||
final int width = options.outWidth;
|
||||
int inSampleSize = 1;
|
||||
|
||||
if (height > destHeight || width > destWidth) {
|
||||
|
||||
final int halfHeight = height / 2;
|
||||
final int halfWidth = width / 2;
|
||||
|
||||
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
|
||||
// height and width larger than the requested height and width.
|
||||
// More informations: http://developer.android.com/training/displaying-bitmaps/load-bitmap.html#load-bitmap
|
||||
while ((halfHeight / inSampleSize) > destHeight
|
||||
&& (halfWidth / inSampleSize) > destWidth) {
|
||||
inSampleSize *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
options.inSampleSize = inSampleSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a byte array to generate a base64 adapted at the destination's size.
|
||||
* Generate a bitmap optimized from the screen sizes.
|
||||
*
|
||||
* @param bytes[] imgBackgroundBase64
|
||||
* @param Options options
|
||||
* @param activity Current activity.
|
||||
* @param data Bytes represent the picture.
|
||||
*
|
||||
* @return Bitmap
|
||||
*/
|
||||
public static Bitmap decodeOptimalPictureFromByteArray(byte[] imgBackgroundBase64, Options options) {
|
||||
public static Bitmap generateOptimizeBitmap(Activity activity, byte[] data) {
|
||||
// Get sizes screen.
|
||||
Display defaultDisplay = activity.getWindowManager().getDefaultDisplay();
|
||||
DisplayMetrics displayMetrics = new DisplayMetrics();
|
||||
defaultDisplay.getMetrics(displayMetrics);
|
||||
int displayWidthPx = (int) displayMetrics.widthPixels;
|
||||
int displayHeightPx = (int) displayMetrics.heightPixels;
|
||||
// Get picture.
|
||||
Options options = BitmapUtils.determineOriginalSizePicture(data);
|
||||
int widthResize = 0;
|
||||
int heightResize = 0;
|
||||
int widthBackground = options.outWidth;
|
||||
int heightBackground= options.outHeight;
|
||||
float ratioX = (float) widthBackground / (float) displayWidthPx;
|
||||
float ratioY = (float) heightBackground / (float) displayHeightPx;
|
||||
int inSampleSize = 1;
|
||||
if (ratioX > ratioY && ratioX > 1) {
|
||||
widthResize = (int) displayWidthPx;
|
||||
heightResize = (int) (heightBackground / ratioX);
|
||||
inSampleSize = (int) ratioX;
|
||||
} else if (ratioX <= ratioY && ratioY > 1) {
|
||||
widthResize = (int) (widthBackground / ratioY);
|
||||
heightResize = (int) displayHeightPx;
|
||||
inSampleSize = (int) ratioY;
|
||||
}
|
||||
options.inSampleSize = inSampleSize;
|
||||
options.inJustDecodeBounds = false;
|
||||
|
||||
return BitmapFactory.decodeByteArray(imgBackgroundBase64, 0, imgBackgroundBase64.length, options);
|
||||
Bitmap picture = BitmapFactory.decodeByteArray(data, 0, data.length, options);
|
||||
data = null;
|
||||
if (widthResize > 0 && heightResize > 0) {
|
||||
picture = Bitmap.createScaledBitmap(picture, widthResize, heightResize, true);
|
||||
}
|
||||
|
||||
return picture;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import android.content.res.Resources.NotFoundException;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Bitmap.CompressFormat;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.BitmapFactory.Options;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
@@ -19,15 +18,14 @@ import android.graphics.drawable.GradientDrawable;
|
||||
import android.graphics.drawable.StateListDrawable;
|
||||
import android.hardware.Camera;
|
||||
import android.hardware.Camera.CameraInfo;
|
||||
import android.hardware.Camera.Parameters;
|
||||
import android.hardware.Camera.PictureCallback;
|
||||
import android.hardware.Camera.ShutterCallback;
|
||||
import android.hardware.Camera.Size;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Display;
|
||||
import android.view.Gravity;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.Surface;
|
||||
@@ -46,11 +44,14 @@ import android.widget.TextView;
|
||||
|
||||
import org.geneanet.customcamera.CameraPreview;
|
||||
import org.geneanet.customcamera.ManagerCamera;
|
||||
import org.geneanet.customcamera.TransferBigData;
|
||||
import org.geneanet.customcamera.BitmapUtils;
|
||||
import org.geneanet.customcamera.TmpFileUtils;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
@@ -65,7 +66,7 @@ public class CameraActivity extends Activity {
|
||||
// Enable miniature mode.
|
||||
private boolean modeMiniature = false;
|
||||
// The image in Bitmap format of the preview photo.
|
||||
private Bitmap photoTaken = null;
|
||||
private Boolean photoTaken = false;
|
||||
// Flag to active or disable opacity function.
|
||||
private Boolean opacity = true;
|
||||
// Flag to save state of flash -> 0 : off, 1 : on, 2 : auto.
|
||||
@@ -82,6 +83,10 @@ public class CameraActivity extends Activity {
|
||||
|
||||
public static final int CAMERA_BACK = 0;
|
||||
public static final int CAMERA_FRONT = 1;
|
||||
|
||||
public static final String NAME_FILE_BACKGROUND = "background";
|
||||
public static final String NAME_FILE_BACKGROUND_OTHER = "background-other";
|
||||
public static final String NAME_FILE_PICTURE_TAKEN = "picture-taken";
|
||||
|
||||
/**
|
||||
* To get camera resource or stop this activity.
|
||||
@@ -292,7 +297,7 @@ public class CameraActivity extends Activity {
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
outState.putBoolean("modeMiniature", modeMiniature);
|
||||
outState.putParcelable("photoTaken", photoTaken);
|
||||
outState.putBoolean("photoTaken", photoTaken);
|
||||
outState.putInt("stateFlash", stateFlash);
|
||||
super.onSaveInstanceState(outState);
|
||||
}
|
||||
@@ -301,7 +306,7 @@ public class CameraActivity extends Activity {
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Bundle savedInstanceState) {
|
||||
modeMiniature = savedInstanceState.getBoolean("modeMiniature");
|
||||
photoTaken = savedInstanceState.getParcelable("photoTaken");
|
||||
photoTaken = savedInstanceState.getBoolean("photoTaken");
|
||||
stateFlash = savedInstanceState.getInt("stateFlash");
|
||||
|
||||
if (modeMiniature) {
|
||||
@@ -328,7 +333,7 @@ public class CameraActivity extends Activity {
|
||||
*/
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
if (photoTaken == null) {
|
||||
if (!photoTaken) {
|
||||
Camera.Parameters paramsCamera = customCamera.getParameters();
|
||||
int action = event.getAction();
|
||||
|
||||
@@ -460,46 +465,25 @@ public class CameraActivity extends Activity {
|
||||
/** To set background in the view. */
|
||||
protected void setBackground() {
|
||||
// Get the base64 picture for the background only if it's exist.
|
||||
byte[] imgBackgroundBase64;
|
||||
byte[] imgBackgroundBase64 = null;
|
||||
File fileBackgroundOther = getFileStreamPath(NAME_FILE_BACKGROUND_OTHER);
|
||||
if (
|
||||
TransferBigData.getImgBackgroundBase64OtherOrientation() == null ||
|
||||
!fileBackgroundOther.exists() ||
|
||||
this.getIntent().getIntExtra("startOrientation", 1)
|
||||
== this.getResources().getConfiguration().orientation
|
||||
) {
|
||||
imgBackgroundBase64 = TransferBigData.getImgBackgroundBase64();
|
||||
imgBackgroundBase64 = TmpFileUtils.getTmpFileContent(this, NAME_FILE_BACKGROUND);
|
||||
} else {
|
||||
imgBackgroundBase64 = TransferBigData.getImgBackgroundBase64OtherOrientation();
|
||||
imgBackgroundBase64 = TmpFileUtils.getTmpFileContent(this, NAME_FILE_BACKGROUND_OTHER);
|
||||
}
|
||||
if (imgBackgroundBase64 != null) {
|
||||
// Get sizes screen.
|
||||
Display defaultDisplay = getWindowManager().getDefaultDisplay();
|
||||
DisplayMetrics displayMetrics = new DisplayMetrics();
|
||||
defaultDisplay.getMetrics(displayMetrics);
|
||||
int displayWidthPx = (int) displayMetrics.widthPixels;
|
||||
int displayHeightPx = (int) displayMetrics.heightPixels;
|
||||
|
||||
// Get picture.
|
||||
Options options = BitmapUtils.determineOriginalSizePicture(imgBackgroundBase64);
|
||||
int widthResize = 0;
|
||||
int heightResize = 0;
|
||||
int widthBackground = options.outWidth;
|
||||
int heightBackground= options.outHeight;
|
||||
float ratioX = (float) displayWidthPx / (float) widthBackground;
|
||||
float ratioY = (float) displayHeightPx / (float) heightBackground;
|
||||
if (ratioX < ratioY && ratioX < 1) {
|
||||
widthResize = (int) displayWidthPx;
|
||||
heightResize = (int) (ratioX * heightBackground);
|
||||
} else if (ratioX >= ratioY && ratioY < 1) {
|
||||
widthResize = (int) (ratioY * widthBackground);
|
||||
heightResize = (int) displayHeightPx;
|
||||
}
|
||||
|
||||
BitmapUtils.determineInSampleSize(options, displayWidthPx, displayHeightPx);
|
||||
Bitmap imgBackgroundBitmap = BitmapUtils.decodeOptimalPictureFromByteArray(imgBackgroundBase64, options);
|
||||
Bitmap imgBackgroundBitmap = BitmapUtils.generateOptimizeBitmap(this, imgBackgroundBase64);
|
||||
imgBackgroundBase64 = null;
|
||||
|
||||
// set image at the view.
|
||||
ImageView background = (ImageView) findViewById(R.id.background);
|
||||
background.setImageBitmap(imgBackgroundBitmap);
|
||||
imgBackgroundBitmap = null;
|
||||
// Opacity at the beginning
|
||||
if (opacity) {
|
||||
background.setAlpha((float)0.5);
|
||||
@@ -507,16 +491,15 @@ public class CameraActivity extends Activity {
|
||||
background.setAlpha((float)1);
|
||||
}
|
||||
|
||||
RelativeLayout.LayoutParams paramsMiniature = new RelativeLayout.LayoutParams(widthResize, heightResize);
|
||||
RelativeLayout.LayoutParams paramsMiniature = (RelativeLayout.LayoutParams) background.getLayoutParams();
|
||||
paramsMiniature.addRule(RelativeLayout.CENTER_IN_PARENT,
|
||||
RelativeLayout.TRUE);
|
||||
|
||||
background.setLayoutParams(paramsMiniature);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize and mask the miniature button.
|
||||
* Resize the picture and change the icon of button.
|
||||
* @param view
|
||||
*/
|
||||
public void buttonMiniature(View view) {
|
||||
@@ -586,7 +569,7 @@ public class CameraActivity extends Activity {
|
||||
// Position at the left
|
||||
paramsMiniature.addRule(RelativeLayout.ALIGN_PARENT_LEFT, RelativeLayout.TRUE);
|
||||
|
||||
if (photoTaken != null) {
|
||||
if (photoTaken) {
|
||||
Resources res = getResources();
|
||||
|
||||
int defaultPadding = (int)res.getDimension(R.dimen.default_padding);
|
||||
@@ -621,7 +604,7 @@ public class CameraActivity extends Activity {
|
||||
switchOpacity.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (photoTaken != null) {
|
||||
if (photoTaken) {
|
||||
// Show/hide elements when a photo is taken
|
||||
keepPhoto.setVisibility(View.VISIBLE);
|
||||
photo.setVisibility(View.GONE);
|
||||
@@ -674,7 +657,7 @@ public class CameraActivity extends Activity {
|
||||
WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
|
||||
Configuration config = getResources().getConfiguration();
|
||||
int rotation = windowManager.getDefaultDisplay().getRotation();
|
||||
|
||||
|
||||
if (
|
||||
(
|
||||
config.orientation == Configuration.ORIENTATION_LANDSCAPE
|
||||
@@ -708,22 +691,12 @@ public class CameraActivity extends Activity {
|
||||
/**
|
||||
* Method to take picture.
|
||||
*/
|
||||
public void takePhoto() {
|
||||
// Handles the moment where picture is taken
|
||||
ShutterCallback shutterCallback = new ShutterCallback() {
|
||||
public void onShutter() {
|
||||
}
|
||||
};
|
||||
|
||||
// Handles data for raw picture
|
||||
PictureCallback rawCallback = new PictureCallback() {
|
||||
public void onPictureTaken(byte[] data, Camera camera) {
|
||||
}
|
||||
};
|
||||
|
||||
public void takePhoto() {
|
||||
setRotationPictureTaken();
|
||||
final CameraActivity cameraActivityCurrent = this;
|
||||
|
||||
// Handles data for jpeg picture
|
||||
PictureCallback jpegCallback = new PictureCallback() {
|
||||
|
||||
/**
|
||||
* Event when picture is taken.
|
||||
* @param byte[] data Picture with byte format.
|
||||
@@ -731,57 +704,55 @@ public class CameraActivity extends Activity {
|
||||
*/
|
||||
public void onPictureTaken(byte[] data, Camera camera) {
|
||||
// Preview from camera
|
||||
photoTaken = BitmapFactory.decodeByteArray(data, 0, data.length);
|
||||
|
||||
// Matrix to perform rotation
|
||||
Matrix mat = new Matrix();
|
||||
int defaultOrientation = getDeviceDefaultOrientation();
|
||||
int orientationCamera = getOrientationOfCamera();
|
||||
int redirect = CameraActivity.DEGREE_0;
|
||||
|
||||
switch (getCustomRotation()) {
|
||||
case 0:
|
||||
redirect = CameraActivity.DEGREE_90;
|
||||
if (ManagerCamera.currentCameraIsFacingFront() || orientationCamera == 1) {
|
||||
redirect = CameraActivity.DEGREE_270;
|
||||
photoTaken = true;
|
||||
|
||||
TmpFileUtils.createTmpFile(cameraActivityCurrent, NAME_FILE_PICTURE_TAKEN, data);
|
||||
|
||||
// Determine if the picture need to be rotated.
|
||||
File filePictureTaken = getFileStreamPath(NAME_FILE_PICTURE_TAKEN);
|
||||
int rotate = TmpFileUtils.determineRotateBasedOnExifFromFilePath(filePictureTaken.getAbsolutePath());
|
||||
if (rotate != 0) {// the picture need to be rotated.
|
||||
// Temporarily storage to use for decoding
|
||||
BitmapFactory.Options opt = new BitmapFactory.Options();
|
||||
opt.inTempStorage = new byte[16 * 1024];
|
||||
FileInputStream fis;
|
||||
Bitmap photoTakenBitmap;
|
||||
try {
|
||||
fis = openFileInput(NAME_FILE_PICTURE_TAKEN);
|
||||
photoTakenBitmap = BitmapFactory.decodeStream(fis, null, opt);
|
||||
fis.close();
|
||||
|
||||
Matrix mat = new Matrix();
|
||||
mat.postRotate(rotate);
|
||||
try {
|
||||
photoTakenBitmap = Bitmap.createBitmap(photoTakenBitmap, 0, 0, photoTakenBitmap.getWidth(), photoTakenBitmap.getHeight(), mat, true);
|
||||
|
||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||
photoTakenBitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
|
||||
byte[] byteArray = stream.toByteArray();
|
||||
stream.close();
|
||||
|
||||
TmpFileUtils.createTmpFile(cameraActivityCurrent, NAME_FILE_PICTURE_TAKEN, byteArray);
|
||||
byteArray = null;
|
||||
} catch (OutOfMemoryError oom) {
|
||||
Log.e("customCamera", "Can't rotate the picture (out of memory).");
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
redirect = CameraActivity.DEGREE_0;
|
||||
break;
|
||||
case 2:
|
||||
// Only on device with landscape mode by default.
|
||||
if (defaultOrientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||
redirect = CameraActivity.DEGREE_270;
|
||||
}
|
||||
if (ManagerCamera.currentCameraIsFacingFront() || orientationCamera == 1) {
|
||||
redirect = CameraActivity.DEGREE_90;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
redirect = CameraActivity.DEGREE_180;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
mat.postRotate(redirect);
|
||||
// We execute a mirror to the matrix in case of front camera.
|
||||
if (ManagerCamera.currentCameraIsFacingFront() || orientationCamera == 1 ) {
|
||||
if (getCustomRotation() == 0 || getCustomRotation() == 2) {
|
||||
mat.preScale(1.0f, -1.0f);
|
||||
} else if (getCustomRotation() == 1 || getCustomRotation() == 3) {
|
||||
mat.preScale(-1.0f, 1.0f);
|
||||
} catch (FileNotFoundException e) {
|
||||
Log.e("customCamera", "Can't load the picture to rotate it.");
|
||||
} catch (IOException e) {
|
||||
Log.e("customCamera", "Can't close the file picture. Error message: "+e.getMessage());
|
||||
} catch (OutOfMemoryError oom) {
|
||||
Log.e("customCamera", "Can't laod the picture.");
|
||||
}
|
||||
|
||||
photoTakenBitmap = null;
|
||||
}
|
||||
|
||||
// Creation of the bitmap
|
||||
photoTaken = Bitmap.createBitmap(photoTaken, 0, 0,
|
||||
photoTaken.getWidth(), photoTaken.getHeight(), mat, true);
|
||||
|
||||
displayPicture();
|
||||
}
|
||||
};
|
||||
// Start capture picture.
|
||||
customCamera.takePicture(shutterCallback, rawCallback, jpegCallback);
|
||||
customCamera.takePicture(null, null, jpegCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -790,13 +761,26 @@ public class CameraActivity extends Activity {
|
||||
*/
|
||||
public void acceptPhoto(View view) {
|
||||
final CameraActivity cameraActivityCurrent = this;
|
||||
|
||||
try {
|
||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||
photoTaken.compress(
|
||||
CompressFormat.JPEG, this.getIntent().getIntExtra("quality", 100), stream);
|
||||
BitmapFactory.Options opt = new BitmapFactory.Options();
|
||||
// Temporarily storage to use for decoding
|
||||
opt.inTempStorage = new byte[16 * 1024];
|
||||
byte[] data = TmpFileUtils.getTmpFileContent(this, NAME_FILE_PICTURE_TAKEN);
|
||||
|
||||
TransferBigData.setImgTaken(stream.toByteArray());
|
||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||
Bitmap photoTakenBitmap;
|
||||
try {
|
||||
photoTakenBitmap = BitmapFactory.decodeByteArray(data, 0, data.length, opt);
|
||||
photoTakenBitmap.compress(
|
||||
CompressFormat.JPEG, this.getIntent().getIntExtra("quality", 100), stream);
|
||||
data = stream.toByteArray();
|
||||
// rewrite the file with the compression.
|
||||
TmpFileUtils.createTmpFile(cameraActivityCurrent, NAME_FILE_PICTURE_TAKEN, data);
|
||||
} catch (OutOfMemoryError oom) {
|
||||
Log.e("customCamera", "Can't compress the picture taken (out of memory).");
|
||||
}
|
||||
photoTakenBitmap = null;
|
||||
stream.close();
|
||||
|
||||
if (this.getIntent().getBooleanExtra("saveInGallery", false)) {
|
||||
// Get path picture to storage.
|
||||
@@ -807,14 +791,16 @@ public class CameraActivity extends Activity {
|
||||
|
||||
// Write data in file.
|
||||
FileOutputStream outStream = new FileOutputStream(pathPicture);
|
||||
outStream.write(TransferBigData.getImgTaken());
|
||||
outStream.write(data);
|
||||
data = null;
|
||||
outStream.close();
|
||||
}
|
||||
|
||||
|
||||
// Return to success & finish current activity.
|
||||
cameraActivityCurrent.setResult(1,new Intent());
|
||||
cameraActivityCurrent.finish();
|
||||
} catch (IOException e) {
|
||||
Log.e("customCamera", "Error to write in file: "+e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -845,7 +831,7 @@ public class CameraActivity extends Activity {
|
||||
customCamera.setParameters(params);
|
||||
}
|
||||
|
||||
photoTaken = null;
|
||||
photoTaken = false;
|
||||
displayPicture();
|
||||
}
|
||||
|
||||
@@ -854,13 +840,28 @@ public class CameraActivity extends Activity {
|
||||
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
|
||||
ImageView photoResized = (ImageView) findViewById(R.id.photoResized);
|
||||
|
||||
if (photoTaken != null) {
|
||||
if (photoTaken) {
|
||||
// Stop link between view and camera to start the preview
|
||||
// picture.
|
||||
customCamera.stopPreview();
|
||||
|
||||
Bitmap newBitmap = resizePictureTaken();
|
||||
byte[] data = TmpFileUtils.getTmpFileContent(this, NAME_FILE_PICTURE_TAKEN);
|
||||
Bitmap newBitmap = BitmapUtils.generateOptimizeBitmap(this, data);
|
||||
|
||||
// rotate the picture of need.
|
||||
File filePictureTaken = getFileStreamPath(NAME_FILE_PICTURE_TAKEN);
|
||||
int rotate = TmpFileUtils.determineRotateBasedOnExifFromFilePath(filePictureTaken.getAbsolutePath());
|
||||
if (rotate != 0) {
|
||||
Matrix mat = new Matrix();
|
||||
mat.postRotate(rotate);
|
||||
try {
|
||||
newBitmap = Bitmap.createBitmap(newBitmap, 0, 0, newBitmap.getWidth(), newBitmap.getHeight(), mat, true);
|
||||
} catch (OutOfMemoryError oom) {
|
||||
Log.e("customCamera", "Can't rotate the picture taken (out of memory).");
|
||||
}
|
||||
}
|
||||
|
||||
photoResized.setImageBitmap(newBitmap);
|
||||
newBitmap = null;
|
||||
photoResized.setVisibility(View.VISIBLE);
|
||||
preview.setVisibility(View.GONE);
|
||||
} else {
|
||||
@@ -871,40 +872,6 @@ public class CameraActivity extends Activity {
|
||||
|
||||
manageDisplayButtons();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize the bitmap saved when you rotate the device.
|
||||
*
|
||||
* @return the new bitmap.
|
||||
*/
|
||||
protected Bitmap resizePictureTaken() {
|
||||
// Initialize the new bitmap resized
|
||||
Bitmap newBitmap = null;
|
||||
|
||||
// Get sizes screen.
|
||||
Display defaultDisplay = getWindowManager().getDefaultDisplay();
|
||||
DisplayMetrics displayMetrics = new DisplayMetrics();
|
||||
defaultDisplay.getMetrics(displayMetrics);
|
||||
int displayWidthPx = (int) displayMetrics.widthPixels;
|
||||
int displayHeightPx = (int) displayMetrics.heightPixels;
|
||||
|
||||
// Get sizes picture.
|
||||
int widthBackground = (int) (photoTaken.getWidth() * displayMetrics.density);
|
||||
int heightBackground = (int) (photoTaken.getHeight() * displayMetrics.density);
|
||||
|
||||
// Change size ImageView.
|
||||
float ratioX = (float) displayWidthPx / (float) widthBackground;
|
||||
float ratioY = (float) displayHeightPx / (float) heightBackground;
|
||||
if (ratioX < ratioY) {
|
||||
newBitmap = Bitmap.createScaledBitmap(photoTaken, (int) displayWidthPx,
|
||||
(int) (ratioX * heightBackground), false);
|
||||
} else if (ratioX >= ratioY) {
|
||||
newBitmap = Bitmap.createScaledBitmap(photoTaken,
|
||||
(int) (ratioY * widthBackground), (int) displayHeightPx, false);
|
||||
}
|
||||
|
||||
return newBitmap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow to lock the screen or not.
|
||||
@@ -944,7 +911,7 @@ public class CameraActivity extends Activity {
|
||||
*/
|
||||
protected int getCustomRotation() {
|
||||
int code = this.getWindowManager().getDefaultDisplay().getRotation();
|
||||
if (getDeviceDefaultOrientation() == 2) {
|
||||
if (getDeviceDefaultOrientation() == Configuration.ORIENTATION_LANDSCAPE) {
|
||||
code ++;
|
||||
}
|
||||
|
||||
@@ -1094,4 +1061,42 @@ public class CameraActivity extends Activity {
|
||||
camParameters.setPreviewSize(optimalSize.width, optimalSize.height);
|
||||
customCamera.setParameters(camParameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* To set the orientation of the picture taken.
|
||||
*/
|
||||
private void setRotationPictureTaken() {
|
||||
int defaultOrientation = getDeviceDefaultOrientation();
|
||||
int orientationCamera = getOrientationOfCamera();
|
||||
int redirect = CameraActivity.DEGREE_0;
|
||||
|
||||
switch (getCustomRotation()) {
|
||||
case 0:
|
||||
redirect = CameraActivity.DEGREE_90;
|
||||
if (ManagerCamera.currentCameraIsFacingFront() || orientationCamera == 1) {
|
||||
redirect = CameraActivity.DEGREE_270;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
redirect = CameraActivity.DEGREE_0;
|
||||
break;
|
||||
case 2:
|
||||
// Only on device with landscape mode by default.
|
||||
if (defaultOrientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||
redirect = CameraActivity.DEGREE_270;
|
||||
}
|
||||
if (ManagerCamera.currentCameraIsFacingFront() || orientationCamera == 1) {
|
||||
redirect = CameraActivity.DEGREE_90;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
redirect = CameraActivity.DEGREE_180;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
Parameters params = customCamera.getParameters();
|
||||
params.setRotation(redirect);
|
||||
customCamera.setParameters(params);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
package org.geneanet.customcamera;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.media.ExifInterface;
|
||||
import android.util.Log;
|
||||
|
||||
public class TmpFileUtils {
|
||||
/**
|
||||
* Create a tmp file in app directory.
|
||||
*
|
||||
* @param activity To storage in tmp directory of the activity.
|
||||
* @param fileName File name.
|
||||
* @param img Image in bytes.
|
||||
*/
|
||||
public static void createTmpFile(Activity activity, String fileName, byte[] img) {
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
fos = activity.openFileOutput(fileName, Context.MODE_PRIVATE);
|
||||
try {
|
||||
fos.write(img);
|
||||
fos.close();
|
||||
} catch (IOException e1) {
|
||||
Log.e("customCamera", "Can't write or close the file: "+fileName);
|
||||
}
|
||||
} catch (FileNotFoundException e1) {
|
||||
Log.e("customCamera", "Can't open the file: "+fileName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file content from this name.
|
||||
*
|
||||
* @param activity To getin tmp directory of the activity.
|
||||
* @param fileName
|
||||
*
|
||||
* @return byte[]
|
||||
*/
|
||||
public static byte[] getTmpFileContent(Activity activity, String fileName) {
|
||||
FileInputStream fis = null;
|
||||
ByteArrayOutputStream ous = null;
|
||||
byte[] returnValue = null;
|
||||
|
||||
try {
|
||||
byte[] buffer = new byte[4096];
|
||||
ous = new ByteArrayOutputStream();
|
||||
fis = activity.openFileInput(fileName);
|
||||
int read = 0;
|
||||
while ( (read = fis.read(buffer)) != -1 ) {
|
||||
ous.write(buffer, 0, read);
|
||||
}
|
||||
fis.close();
|
||||
returnValue = ous.toByteArray();
|
||||
ous.close();
|
||||
} catch (FileNotFoundException e) {
|
||||
Log.e("customCamera", "Can't open the file: "+fileName);
|
||||
} catch (IOException e1) {
|
||||
Log.e("customCamera", "Can't read or close the file: "+fileName);
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* determine the rotate for a picture based on exif data.
|
||||
*
|
||||
* @param filePath
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static int determineRotateBasedOnExifFromFilePath(String filePath) {
|
||||
ExifInterface exif;
|
||||
int rotate = 0;
|
||||
try {
|
||||
exif = new ExifInterface(filePath);
|
||||
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
|
||||
|
||||
switch (orientation) {
|
||||
case ExifInterface.ORIENTATION_ROTATE_270:
|
||||
rotate = 270;
|
||||
break;
|
||||
case ExifInterface.ORIENTATION_ROTATE_180:
|
||||
rotate = 180;
|
||||
break;
|
||||
case ExifInterface.ORIENTATION_ROTATE_90:
|
||||
rotate = 90;
|
||||
break;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.e("customCamera", "Can't determine EXIF orientation of :"+filePath+". Error message: "+e.getMessage());
|
||||
}
|
||||
|
||||
return rotate;
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
package org.geneanet.customcamera;
|
||||
|
||||
/**
|
||||
* Use to transfer big data between activities.
|
||||
*/
|
||||
public class TransferBigData {
|
||||
protected static byte[] imgBackgroundBase64 = null;
|
||||
protected static byte[] imgBackgroundBase64OtherOrientation = null;
|
||||
protected static byte[] imgTaken = null;
|
||||
|
||||
/**
|
||||
* Get bytes to represent background picture.
|
||||
*
|
||||
* @return byte[]
|
||||
*/
|
||||
public static byte[] getImgBackgroundBase64() {
|
||||
return TransferBigData.imgBackgroundBase64;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set bytes to represent background picture.
|
||||
*
|
||||
* @param byte[] imgBackgroundBase64
|
||||
*/
|
||||
public static void setImgBackgroundBase64(byte[] imgBackgroundBase64) {
|
||||
TransferBigData.imgBackgroundBase64 = imgBackgroundBase64;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bytes to represent background picture for OtherOrientation.
|
||||
*
|
||||
* @return byte[]
|
||||
*/
|
||||
public static byte[] getImgBackgroundBase64OtherOrientation() {
|
||||
return TransferBigData.imgBackgroundBase64OtherOrientation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set bytes to represent background picture for OtherOrientation.
|
||||
*
|
||||
* @param byte[] imgBackgroundBase64OtherOrientation
|
||||
*/
|
||||
public static void setImgBackgroundBase64OtherOrientation(byte[] imgBackgroundBase64OtherOrientation) {
|
||||
TransferBigData.imgBackgroundBase64OtherOrientation = imgBackgroundBase64OtherOrientation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bytes to represent picture taken.
|
||||
*
|
||||
* @return byte[]
|
||||
*/
|
||||
public static byte[] getImgTaken() {
|
||||
return TransferBigData.imgTaken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set bytes to represent picture taken.
|
||||
*
|
||||
* @param byte[] imgTaken
|
||||
*/
|
||||
public static void setImgTaken(byte[] imgTaken) {
|
||||
TransferBigData.imgTaken = imgTaken;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user