"JavaCameraView" Camera Orientation Issue - android

I am new to Android development. I'm making a simple app, which has one Activity. In this Activity I'm trying to get frames from camera and process it real time, but I'm having camera orientation Issue, i.e. image received is 90 degree rotated. There are many solutions available to solve this problem but found no one for the "JavaCameraView". So please help me out how to solve the orientation issue only for "JavaCameraView".
This is my code:
public class MainActivity extends AppCompatActivity implements CameraBridgeViewBase.CvCameraViewListener2 {
private static final String TAG = "MainActivity";
JavaCameraView javaCameraView;
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
#Override
public void onManagerConnected(int status) {
switch (status) {
case LoaderCallbackInterface.SUCCESS: {
javaCameraView.enableView();
}
break;
default: {
super.onManagerConnected(status);
}
break;
}
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, CAMERA_PERMISSION_REQUEST_CODE);
//}
javaCameraView = (JavaCameraView) findViewById(R.id.java_camera_view);
javaCameraView.setVisibility(View.VISIBLE);
javaCameraView.setCvCameraViewListener(this);
}
#Override
protected void onPause() {
super.onPause();
if (javaCameraView != null)
javaCameraView.disableView();
}
#Override
protected void onDestroy() {
super.onDestroy();
if (javaCameraView != null)
javaCameraView.disableView();
}
#Override
protected void onResume() {
super.onResume();
if (OpenCVLoader.initDebug()) {
Log.i(TAG, "OpenCV loaded successfully.");
mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
} else {
Log.i(TAG, "OpenCV not loaded.");
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_1_0, this, mLoaderCallback);
}
}
#Override
public void onCameraViewStarted(int width, int height) {
frame = new Mat(height, width, CV_8UC4);
}
#Override
public void onCameraViewStopped() {
frame.release();
}
#Override
public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
frame = inputFrame.rgba();
//frame=processFrame();
//Imgcodecs.imwrite("/storage/emulated/0/aaaaa+.jpg", frame);
return frame;
}
}

I have solve this issue :
Use below class instead of javaCameraView :
public class PortraitCameraView extends CameraBridgeViewBase implements Camera.PreviewCallback {
private static final int MAGIC_TEXTURE_ID = 10;
private static final String TAG = "JavaCameraView";
private byte mBuffer[];
private Mat[] mFrameChain;
private int mChainIdx = 0;
private Thread mThread;
private boolean mStopThread;
public Camera mCamera;
protected JavaCameraFrame[] mCameraFrame;
private SurfaceTexture mSurfaceTexture;
private int mCameraId;
Handler handler;
boolean callBuffer = false;
Camera.Size bestSize = null;
Camera.Size pictureSize = null;
private LayoutMode mLayoutMode;
private int mCenterPosX = -1;
private int mCenterPosY;
public static enum LayoutMode {
FitToParent, // Scale to the size that no side is larger than the parent
NoBlank // Scale to the size that no side is smaller than the parent
}
public static class JavaCameraSizeAccessor implements ListItemAccessor {
public int getWidth(Object obj) {
Camera.Size size = (Camera.Size) obj;
return size.width;
}
public int getHeight(Object obj) {
Camera.Size size = (Camera.Size) obj;
return size.height;
}
}
public PortraitCameraView(Context context, int cameraId) {
super(context, cameraId);
}
public PortraitCameraView(Context context, AttributeSet attrs) {
super(context, attrs);
}
protected boolean initializeCamera(int width, int height) {
handler = new Handler();
Log.d(TAG, "Initialize java camera");
boolean result = true;
synchronized (this) {
mCamera = null;
boolean connected = false;
int numberOfCameras = android.hardware.Camera.getNumberOfCameras();
android.hardware.Camera.CameraInfo cameraInfo = new android.hardware.Camera.CameraInfo();
for (int i = 0; i < numberOfCameras; i++) {
android.hardware.Camera.getCameraInfo(i, cameraInfo);
if (cameraInfo.facing == android.hardware.Camera.CameraInfo.CAMERA_FACING_BACK) {
try {
mCamera = Camera.open(i);
mCameraId = i;
connected = true;
} catch (RuntimeException e) {
Log.e(TAG, "Camera #" + i + "failed to open: " + e.getMessage());
}
if (connected) break;
}
}
if (mCamera == null) return false;
/* Now set camera parameters */
try {
Camera.Parameters params = mCamera.getParameters();
List<Camera.Size> sizes = params.getSupportedPreviewSizes();
List<Camera.Size> Picturesizes = params.getSupportedPictureSizes();
pictureSize = Picturesizes.get(0);
List<Camera.Size> sizeList = sizes;
bestSize = sizeList.get(0);
Log.d(TAG, "getSupportedPreviewSizes() " + bestSize.width + " " + bestSize.height);
Log.d(TAG, "Picturesizes() " + pictureSize.width + " " + pictureSize.height);
// bestSize.width = GlobalArea.display_width;
//// bestSize.height = GlobalArea.display_height;
for (int i = 1; i < sizeList.size(); i++) {
if ((sizeList.get(i).width * sizeList.get(i).height) > (bestSize.width * bestSize.height)) {
Log.d(TAG, "getSupportedPreviewSizes() " + sizeList.get(i).width + " " + sizeList.get(i).height);
bestSize = sizeList.get(i);
}
}
if (sizes != null) {
/* Select the size that fits surface considering maximum size allowed */
Size frameSize = calculateCameraFrameSize(sizes, new JavaCameraSizeAccessor(), height, width); //use turn around values here to get the correct prev size for portrait mode
params.setPreviewFormat(ImageFormat.NV21);
Log.e(TAG, "Set preview size to " + Integer.valueOf((int) bestSize.width) + " x " + Integer.valueOf((int) bestSize.height));
Log.e(TAG, "Set preview size to " + width + " x " + height);
params.setPreviewSize((int) bestSize.width, (int) bestSize.height);
params.setPictureSize((int) pictureSize.width, (int) pictureSize.height);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
params.setRecordingHint(true);
List<String> FocusModes = params.getSupportedFocusModes();
if (FocusModes != null && FocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
}
boolean hasFlash = SevenBitsDemo.getInstance().getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
if (hasFlash) {
// mOpenCvCameraView.flashOn();
params.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
}
List<int[]> ints = params.getSupportedPreviewFpsRange();
for (int i = 0; i < ints.size(); i++) {
Log.e("privew size", String.valueOf(ints.get(i).length));
}
// params.setPreviewFpsRange(10000,10000);
mCamera.setParameters(params);
// boolean mSurfaceConfiguring = adjustSurfaceLayoutSize(bestSize, true, width, height);
params = mCamera.getParameters();
GlobalArea.preview_size = params.getPreviewSize();
mFrameWidth = params.getPreviewSize().height; //the frame width and height of the super class are used to generate the cached bitmap and they need to be the size of the resulting frame
mFrameHeight = params.getPreviewSize().width;
int realWidth = mFrameHeight; //the real width and height are the width and height of the frame received in onPreviewFrame ...
int realHeight = mFrameWidth;
if ((getLayoutParams().width == LinearLayout.LayoutParams.MATCH_PARENT) && (getLayoutParams().height == LinearLayout.LayoutParams.MATCH_PARENT))
mScale = Math.min(((float) height) / mFrameHeight, ((float) width) / mFrameWidth);
else
mScale = 0;
if (mFpsMeter != null) {
mFpsMeter.setResolution((int) pictureSize.width, (int) pictureSize.height);
}
int size = mFrameWidth * mFrameHeight;
size = size * ImageFormat.getBitsPerPixel(params.getPreviewFormat()) / 8;
mBuffer = new byte[size];
mCamera.addCallbackBuffer(mBuffer);
mCamera.setPreviewCallbackWithBuffer(this);
mFrameChain = new Mat[2];
mFrameChain[0] = new Mat(realHeight + (realHeight / 2), realWidth, CvType.CV_8UC1); //the frame chane is still in landscape
mFrameChain[1] = new Mat(realHeight + (realHeight / 2), realWidth, CvType.CV_8UC1);
AllocateCache();
mCameraFrame = new JavaCameraFrame[2];
mCameraFrame[0] = new JavaCameraFrame(mFrameChain[0], mFrameWidth, mFrameHeight); //the camera frame is in portrait
mCameraFrame[1] = new JavaCameraFrame(mFrameChain[1], mFrameWidth, mFrameHeight);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
mSurfaceTexture = new SurfaceTexture(MAGIC_TEXTURE_ID);
mCamera.setPreviewTexture(mSurfaceTexture);
} else
mCamera.setPreviewDisplay(null);
/* Finally we are ready to start the preview */
Log.d(TAG, "startPreview");
mCamera.startPreview();
} else
result = false;
} catch (Exception e) {
result = false;
e.printStackTrace();
}
}
return result;
}
protected void releaseCamera() {
synchronized (this) {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.setPreviewCallback(null);
mCamera.release();
}
mCamera = null;
if (mFrameChain != null) {
mFrameChain[0].release();
mFrameChain[1].release();
}
if (mCameraFrame != null) {
mCameraFrame[0].release();
mCameraFrame[1].release();
}
}
}
#Override
protected boolean connectCamera(int width, int height) {
/* 1. We need to instantiate camera
* 2. We need to start thread which will be getting frames
*/
/* First step - initialize camera connection */
Log.d(TAG, "Connecting to camera");
if (!initializeCamera(width, height))
return false;
/* now we can start update thread */
Log.d(TAG, "Starting processing thread");
mStopThread = false;
mThread = new Thread(new CameraWorker());
mThread.start();
return true;
}
protected void disconnectCamera() {
/* 1. We need to stop thread which updating the frames
* 2. Stop camera and release it
*/
Log.d(TAG, "Disconnecting from camera");
try {
mStopThread = true;
Log.d(TAG, "Notify thread");
synchronized (this) {
this.notify();
}
Log.d(TAG, "Wating for thread");
if (mThread != null)
mThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
mThread = null;
}
/* Now release camera */
releaseCamera();
}
public void onPreviewFrame(byte[] frame, Camera arg1) {
synchronized (this) {
mFrameChain[1 - mChainIdx].put(0, 0, frame);
this.notify();
}
if (mCamera != null)
mCamera.addCallbackBuffer(mBuffer);
}
private class JavaCameraFrame implements CvCameraViewFrame {
private Mat mYuvFrameData;
private Mat mRgba;
private int mWidth;
private int mHeight;
private Mat mRotated;
public Mat gray() {
if (mRotated != null) mRotated.release();
mRotated = mYuvFrameData.submat(0, mWidth, 0, mHeight);
//submat with reversed width and height because its done on the
landscape frame
mRotated = mRotated.t();
Core.flip(mRotated, mRotated, 1);
return mRotated;
}
public Mat rgba() {
Imgproc.cvtColor(mYuvFrameData, mRgba, Imgproc.COLOR_YUV2BGR_NV12, 4);
if (mRotated != null) mRotated.release();
mRotated = mRgba.t();
Core.flip(mRotated, mRotated, 1);
return mRotated;
}
public JavaCameraFrame(Mat Yuv420sp, int width, int height) {
super();
mWidth = width;
mHeight = height;
mYuvFrameData = Yuv420sp;
mRgba = new Mat();
}
public void release() {
mRgba.release();
if (mRotated != null) mRotated.release();
}
}
private class CameraWorker implements Runnable {
public void run() {
do {
synchronized (PortraitCameraView.this) {
try {
PortraitCameraView.this.wait();
} catch (InterruptedException e) {
Log.e(TAG, "CameraWorker interrupted", e);
}
}
if (!mStopThread) {
if (!mFrameChain[mChainIdx].empty())
deliverAndDrawFrame(mCameraFrame[mChainIdx]);
mChainIdx = 1 - mChainIdx;
}
} while (!mStopThread);
Log.d(TAG, "Finish processing thread");
}
}
}
So now use PortraitCameraView in your xml and java file because i have convert javacamera view in portrait mode in this class.

You can use setMaxFrame size function.
javaCameraView.setMaxFrameSize(480, 640);
480 is width and 640 is height. Now javacameraview is portrait.

Related

How resize the image bitmap with the custom layout height and width

I am using the fallowing solution to resize the bitmap. But it results portion of the image is lost.
Here is is my code.
BitmapFactory.Options bmFactoryOptions = new BitmapFactory.Options();
bmFactoryOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
bmFactoryOptions.inMutable = true;
bmFactoryOptions.inSampleSize = 2;
Bitmap originalCameraBitmap = BitmapFactory.decodeByteArray(pData, 0, pData.length, bmFactoryOptions);
rotatedBitmap = getResizedBitmap(originalCameraBitmap, cameraPreviewLayout.getHeight(), cameraPreviewLayout.getWidth() - preSizePriviewHight(), (int) rotationDegrees);
public Bitmap getResizedBitmap(Bitmap bm, int newWidth, int newHeight, int angle) {
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
Matrix matrix = new Matrix();
matrix.postRotate(angle);
matrix.postScale(scaleWidth, scaleHeight);
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, true);
DeliverItApplication.getInstance().setImageCaptured(true);
return resizedBitmap;
}
And here is the image height and width : Preview surface size:352:288 Before resized bitmap width : 320 Height : 240 CameraPreviewLayout width : 1080 Height : 1362 Resized bitmap width : 1022 Height : 1307
Your java code is right but you haven't care about Aspect Ratio of Image thats whys your Image Portion is cutting.
Original Image Height and Width :
Height = 352;
Width = 288;
Aspect Ratio = h/w; => Ratio = 1.2;
and you taken new width and height :
newHeight = 320;
newWidth = 240;
But if we take Image Height as 320 then according Image Aspect Ratio Its Width becomes :
calculated width = newHeight /Ratio; => 320/1.2= 266.66= 267;
calculated width = 267;
difference of portion cutting is = calculated width -newWidth;
= 267 -240 ;
= 27 ;
So you need to take height and width for new bitmap.
newHeight = 320;
newWidth = 267 ;
public class MarkableImageCaptureActivity extends Activity implements OnClickListener {
private static Logger logger = LoggerFactory.getLogger(MarkableImageCaptureActivity.class);
#InjectView(R.id.top_menu_bar)
private LinearLayout topMenuLayout;
#InjectView(R.id.top_menu_title)
private TextView topMenuTitleTV;
#InjectView(R.id.image_desc_edittext)
private EditText imageDescEditText;
#InjectView(R.id.camerapreview_layout)
private FrameLayout cameraPreviewLayout;
#InjectView(R.id.btn_camera_capture)
private Button captureBtn;
#InjectView(R.id.btn_camera_save)
private Button saveBtn;
#InjectView(R.id.btn_camera_cancel)
private Button cancelBtn;
#InjectView(R.id.edit_captured_image_layout)
private RelativeLayout editCapturedImageLayout;
#InjectView(R.id.edit_captured_image)
private ImageView editCapturedImage;
#InjectView(R.id.color_container_layout)
private LinearLayout colorContainerLayout;
#InjectView(R.id.btn_markable_red)
private Button btnMarkableRed;
#InjectView(R.id.btn_markable_blue)
private Button btnMarkableBlue;
#InjectView(R.id.btn_markable_green)
private Button btnMarkableGreen;
#InjectView(R.id.btn_markable_white)
private Button btnMarkableWhite;
#InjectView(R.id.btn_markable_black)
private Button btnMarkableBlack;
#InjectView(R.id.btn_undo)
private TextView capturedImageUndo;
private MarkableImageView editableCapturedImageview;
#InjectView(R.id.flashSwitch)
private ToggleButton flashToggle;
private static final int DIALOG_CAPTURE_EXCEPTION = 2101;
private static final int DIALOG_CAPTURING_EXCEPTION = 2102;
private static final int DIALOG_SAVE_EXCEPTION = 0;
private String imageFileName = null;
private File imageFile = null;
private Stop targetStop = null;
private int stopId = DIntent.VALUE_INVALID_ID;
private float rotationDegrees = 0;
private Camera camera = null;
private CameraPreview cameraPreview;
private Bitmap rotatedBitmap;
private static final int PRIMARY_CAMERA_ID = 0;
private boolean imageCaptured = false;
private boolean inPreview = false;
private boolean isFlashSupports;
private boolean isCapturing = false;
private boolean isFlashOn;
private boolean isDocNameEditable;
private String imageDesc = "";
private Handler focusHandler = null;
private int captureType;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_start_camera_for_photo_capture);
setupTopMenuBar(topMenuLayout, null, getString(R.string.menuitem_back), getString(R.string.menuitem_done), true, true, new ImageCaptureTopMenuListener());
focusHandler = new Handler();
editableCapturedImageview = (MarkableImageView) findViewById(R.id.editable_captured_imageview);
Bundle intentBundle = getIntent().getExtras();
isDocNameEditable = getIntent().getBooleanExtra(DIntent.EXTRA_OBJECT_TYPE_DOCUMENT_EDITABLE, false);
imageDesc = getIntent().getStringExtra(DIntent.EXTRA_OBJECT_TYPE_DOCUMENT_NAME);
if (savedInstanceState != null) {
stopId = savedInstanceState.getInt(DIntent.EXTRA_STOP_ID);
imageDesc = savedInstanceState.getString(DIntent.EXTRA_IMAGE_DESC);
imageCaptured = savedInstanceState.getBoolean(DIntent.EXTRA_IS_IMAGE_CAPTURED);
inPreview = savedInstanceState.getBoolean(DIntent.EXTRA_IN_PREVIEW);
isFlashOn=savedInstanceState.getBoolean(DIntent.FLASH_MODE_ON);
if (imageCaptured) {
rotatedBitmap = savedInstanceState.getParcelable(DIntent.EXTRA_IMAGE_BITMAP);
}
}
captureType = intentBundle.getInt(DIntent.EXTRA_TYPE_CAPTURE);
if (captureType == DIntent.EXTRA_TYPE_IMAGE_CAPTURE) {
stopId = intentBundle.getInt(DIntent.EXTRA_STOP_ID);
try {
targetStop = getDbHelper().getStopDao().queryForId(stopId);
} catch (SQLException e) {
logger.error("Exception finding stop by Id!!", e);
}
}
isFlashSupports = getApplicationContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
if (isFlashSupports) {
flashToggle.setVisibility(View.VISIBLE);
flashToggle.setOnClickListener(this);
} else {
flashToggle.setVisibility(View.GONE);
}
captureBtn.setOnClickListener(this);
saveBtn.setOnClickListener(this);
cancelBtn.setOnClickListener(this);
imageDescEditText.setText(imageDesc);
if (AndroidUtility.isValidTrimmedString(imageDesc)) {
if (!isDocNameEditable) {
imageDescEditText.setEnabled(false);
}
} else {
imageDescEditText.setEnabled(true);
}
editCapturedImage.setOnClickListener(this);
btnMarkableWhite.setOnClickListener(this);
btnMarkableRed.setOnClickListener(this);
btnMarkableBlue.setOnClickListener(this);
btnMarkableGreen.setOnClickListener(this);
btnMarkableBlack.setOnClickListener(this);
capturedImageUndo.setOnClickListener(this);
}
#Override
protected void onStart() {
super.onStart();
logger.info("onStart:imageCaptured" + imageCaptured);
boolean isImageCaptured = DeliverItApplication.getInstance().isImageCaptured();
if (!isImageCaptured) {
if (rotatedBitmap != null) {
activateCapturedImageView(rotatedBitmap);
} else {
activatePreviewLayout();
}
}
}
private void activateCapturedImageView(Bitmap rotatedBitmap) {
cameraPreviewLayout.setVisibility(View.GONE);
editableCapturedImageview.setCapturedBitmap(rotatedBitmap);
editableCapturedImageview.setVisibility(View.VISIBLE);
editCapturedImageLayout.setVisibility(View.VISIBLE);
captureBtn.setVisibility(View.GONE);
saveBtn.setVisibility(View.VISIBLE);
saveBtn.requestFocus();
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) editableCapturedImageview.getLayoutParams();
layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
layoutParams.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE);
layoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL, RelativeLayout.TRUE);
layoutParams.width = rotatedBitmap.getWidth();
layoutParams.height = rotatedBitmap.getHeight();
editableCapturedImageview.setLayoutParams(layoutParams);
logger.info("Inside activateCapturedImageView");
releaseCamera();
}
private void activatePreviewLayout() {
logger.info("Insie activatePreviewLayout");
cameraPreviewLayout.setVisibility(View.VISIBLE);
editableCapturedImageview.setVisibility(View.GONE);
editCapturedImageLayout.setVisibility(View.GONE);
captureBtn.setVisibility(View.VISIBLE);
captureBtn.requestFocus();
saveBtn.setVisibility(View.GONE);
}
#Override
protected void onResume() {
super.onResume();
logger.info("onResume");
if (rotatedBitmap == null || inPreview) {
activateCameraPreview();
}
}
public void activateCameraPreview() {
logger.info("activateCameraPreview");
camera = getCameraInstance(camera);
if (camera != null) {
cameraPreview = new CameraPreview(this, camera);
rotationDegrees = getCameraDisplayOrientation(this, PRIMARY_CAMERA_ID);
camera.setDisplayOrientation((int) rotationDegrees);
cameraPreviewLayout.addView(cameraPreview);
inPreview = true;
isCapturing = false;
Camera.Parameters params = camera.getParameters();
if (isFlashSupported(params)) {
logger.info("activateCameraPreview: Flash Mode:"+ isFlashOn);
if (isFlashOn) {
params.setFlashMode(Camera.Parameters.FLASH_MODE_ON);
} else {
params.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
}
} else {
flashToggle.setVisibility(View.GONE);
}
camera.setParameters(params);
enableAutoFocusMode(camera);
}
}
private Runnable doFocusRunnable = new Runnable() {
#Override
public void run() {
if (camera != null) {
focusHandler.removeCallbacks(doFocusRunnable);
if (CameraPreview.isCameraPreviewStarted) {
try {
camera.autoFocus(autoFocusCallback);
logger.info("doFocusRunnable autofocus set");
} catch (Exception e) {
logger.error("Error while calling autofocus in camera."+e);
}
} else {
logger.info("doFocusRunnable isCameraPreviewStarted false. Postdelay for 2 seconds");
focusHandler.postDelayed(doFocusRunnable, 2000);
}
}
}
};
Camera.AutoFocusCallback autoFocusCallback = new Camera.AutoFocusCallback(){
#Override
public void onAutoFocus(boolean arg0, Camera arg1) {
if (camera != null) {
logger.info("Excuting onAutoFocus callback");
focusHandler.postDelayed(doFocusRunnable, 2000);
}
}
};
public Camera getCameraInstance(Camera oldCamera) {
Camera newCamera = null;
try {
logger.info("attempt to get a Camera instance");
if (oldCamera == null) {
logger.info("oldCamera is null.Opening Camera");
newCamera = Camera.open(PRIMARY_CAMERA_ID);
} else {
logger.info("oldCamera is not null.Releasing it and Opening Camera");
oldCamera.release();
newCamera = Camera.open(PRIMARY_CAMERA_ID);
}
} catch (Exception e) {
logger.info("Camera is not available (in use or does not exist)");
}
return newCamera; // returns null if camera is unavailable
}
#Override
protected void onPause() {
super.onPause();
logger.info("onPause");
releaseCamera();
}
private void releaseCamera() {
if (null != camera) {
try {
focusHandler.removeCallbacks(doFocusRunnable);
CameraPreview.isCameraPreviewStarted = false;
camera.cancelAutoFocus();
camera.stopPreview();
camera.release();
camera = null;
cameraPreview.setVisibility(View.GONE);
cameraPreview = null;
inPreview = false;
logger.info("Camera released successfully ");
} catch (Exception e) {
logger.error("Error while releasing camera in releaseCamera()."+e);
}
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
logger.info("onSaveInstanceState");
outState.putInt(DIntent.EXTRA_STOP_ID, stopId);
outState.putBoolean(DIntent.EXTRA_IS_IMAGE_CAPTURED, imageCaptured);
outState.putBoolean(DIntent.EXTRA_IN_PREVIEW, inPreview);
outState.putString(DIntent.EXTRA_IMAGE_DESC, imageDesc);
}
#Override
protected void onDestroy() {
super.onDestroy();
logger.info("onDestroy");
DeliverItApplication.getInstance().setImageCaptured(false);
}
public float getCameraDisplayOrientation(Activity activity, int cameraId) {
CameraInfo info = new CameraInfo();
Camera.getCameraInfo(cameraId, info);
int displayOrientation = activity.getWindowManager().getDefaultDisplay().getRotation();
int infoOrientation = info.orientation;
float degrees = 0;
switch (displayOrientation) {
case Surface.ROTATION_0:
degrees = 0;
break;
case Surface.ROTATION_90:
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}
float result;
if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
logger.info("Camera.CameraInfo.CAMERA_FACING_FRONT");
result = (infoOrientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
logger.info("Camera.CameraInfo.CAMERA_FACING_BACK");
result = (infoOrientation - degrees + 360) % 360;
}
logger.info("Display Rotation:" + displayOrientation + " & infoOrientation:" + infoOrientation + " & degrees:"
+ degrees + " & info.facing:" + info.facing + " & result:" + result);
return result;
}
private void captureImage() {
try {
if (camera != null) {
//camera.autoFocus(autoFocusCallback);
isCapturing = true;
logger.info("Taking picture while clicking Capture button");
camera.takePicture(null, null, pictureCallBack);
} else {
if (rotatedBitmap == null) {
showDialog(DIALOG_CAMERA_UNAVAILABLE);
}
}
} catch (Exception e) {
releaseCamera();
logger.error("Error in camera initialization in StartCaptureForPhoto screen.");
activatePreviewLayout();
activateCameraPreview();
}
}
private PictureCallback pictureCallBack = new PictureCallback() {
#Override
public void onPictureTaken(byte[] pData, Camera pCamera) {
BitmapFactory.Options bmFactoryOptions = new BitmapFactory.Options();
bmFactoryOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
bmFactoryOptions.inMutable = true;
// bmFactoryOptions.inSampleSize = 2;
Bitmap originalCameraBitmap = BitmapFactory.decodeByteArray(pData, 0, pData.length, bmFactoryOptions);
logger.info("before resized bitmap width : "+originalCameraBitmap.getWidth() + " Hieght : "+ originalCameraBitmap.getHeight());
rotatedBitmap = getResizedBitmap(originalCameraBitmap, cameraPreviewLayout.getHeight(), cameraPreviewLayout.getWidth() - preSizePriviewHight(), (int) rotationDegrees);
logger.info("cameraPreviewLayout width : "+cameraPreviewLayout.getWidth() + " Hieght : "+ cameraPreviewLayout.getHeight());
if (rotatedBitmap != null) {
imageCaptured = true;
activateCapturedImageView(rotatedBitmap);
} else {
imageCaptured = false;
}
isCapturing = false;
originalCameraBitmap.recycle();
flashToggle.setVisibility(View.GONE);
}
};
public Bitmap getResizedBitmap(Bitmap bm, int newWidth, int newHeight, int angle) {
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
Matrix matrix = new Matrix();
matrix.postRotate(angle);
matrix.postScale(scaleWidth, scaleHeight);
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, true);
DeliverItApplication.getInstance().setImageCaptured(true);
return resizedBitmap;
}
#Override
public void onClick(View pView) {
switch (pView.getId()) {
case R.id.btn_camera_capture:
if (!isCapturing) {
captureImage();
} else {
logger.error("Picture being captured.User clicked so fast.");
}
break;
case R.id.btn_camera_save:
if (imageCaptured) {
String description = imageDescEditText.getText().toString();
if (description != null && description.length() > 0) {
saveCapturedImage();
} else {
imageDescEditText.setError((getString(R.string.error_photo_desc)));
}
}
break;
case R.id.edit_captured_image:
colorContainerLayout.setVisibility(View.VISIBLE);
capturedImageUndo.setVisibility(View.VISIBLE);
editableCapturedImageview.setPaintBrushColor(Color.WHITE);
break;
case R.id.btn_markable_green:
editableCapturedImageview.setPaintBrushColor(Color.parseColor("#6AD523"));
break;
case R.id.btn_markable_blue:
editableCapturedImageview.setPaintBrushColor(Color.parseColor("#407FF0"));
break;
case R.id.btn_markable_red:
editableCapturedImageview.setPaintBrushColor(Color.parseColor("#B0321B"));
break;
case R.id.btn_markable_white:
editableCapturedImageview.setPaintBrushColor(Color.parseColor("#F7F5FA"));
break;
case R.id.btn_markable_black:
editableCapturedImageview.setPaintBrushColor(Color.parseColor("#2A2A2C"));
break;
case R.id.btn_undo:
editableCapturedImageview.onClickUndo();
break;
case R.id.btn_camera_cancel:
releaseCamera();
finish();
break;
case R.id.flashSwitch:
switchFlash();
default:
break;
}
}
#Override
protected Dialog onCreateDialog(int id, Bundle bundle) {
switch (id) {
case DIALOG_CAPTURE_EXCEPTION:
DIAlertDialog captureErrorDialog = new DIAlertDialog(this, getText(R.string.dialog_camera_error)
.toString(), getText(R.string.dialog_capture_exception).toString(), null, null);
return captureErrorDialog;
case DIALOG_SAVE_EXCEPTION:
DIAlertDialog imageSaveErrorDialog = new DIAlertDialog(this, getText(R.string.dialog_camera_error)
.toString(), getText(R.string.dialog_image_save_exception).toString(), null, null);
return imageSaveErrorDialog;
case DIALOG_CAPTURING_EXCEPTION:
DIAlertDialog capturingDialog = new DIAlertDialog(this, getText(R.string.dialog_camera_error)
.toString(), getText(R.string.dialog_capturing_exception).toString(), null, null);
return capturingDialog;
default:
return super.onCreateDialog(id, bundle);
}
}
private class ImageCaptureTopMenuListener implements OnClickListener {
#Override
public void onClick(View v) {
if (v.getVisibility() == View.VISIBLE && v.getId() == R.id.top_left_menu_item) {
onBackPressed();
} else if (v.getVisibility() == View.VISIBLE && v.getId() == R.id.top_right_menu_item) {
if (imageCaptured) {
String description = imageDescEditText.getText().toString();
if (description != null && description.length() > 0) {
saveCapturedImage();
} else {
imageDescEditText.setError((getString(R.string.error_photo_desc)));
}
}
}
}
}
private void switchFlash() {
if (camera == null) {
return;
}
if (!isFlashOn) {
Camera.Parameters params = camera.getParameters();
params.setFlashMode(Camera.Parameters.FLASH_MODE_ON);
camera.setParameters(params);
if (rotatedBitmap != null) {
activateCapturedImageView(rotatedBitmap);
} else {
activatePreviewLayout();
}
isFlashOn = true;
} else {
Camera.Parameters params = camera.getParameters();
params.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
camera.setParameters(params);
if (rotatedBitmap != null) {
activateCapturedImageView(rotatedBitmap);
} else {
activatePreviewLayout();
}
isFlashOn = false;
}
}
private int preSizePriviewHight() {
int defaultSize = 100;
switch (getResources().getDisplayMetrics().densityDpi) {
case DisplayMetrics.DENSITY_LOW:
defaultSize = 75;
break;
case DisplayMetrics.DENSITY_MEDIUM:
defaultSize = 80;
break;
case DisplayMetrics.DENSITY_HIGH:
defaultSize = 120;
break;
case DisplayMetrics.DENSITY_XHIGH:
defaultSize = 160;
break;
case DisplayMetrics.DENSITY_XXHIGH:
defaultSize = 430;
break;
case DisplayMetrics.DENSITY_XXXHIGH:
defaultSize = 460;
break;
default:
break;
}
return defaultSize;
}
private void enableAutoFocusMode(Camera camera) {
try {
Camera.Parameters params = camera.getParameters();
List<String> focusParameterList = params.getSupportedFocusModes();
if (focusParameterList != null && focusParameterList.size() > 0) {
logger.info("Supported focus mode:"+focusParameterList);
if (focusParameterList.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
logger.info("enableAutoFocusMode: Starting focus mode");
params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
camera.setParameters(params);
/*
Below line commented due to crash issue in focus mode because of autoFocus call before start preview
So we are giving 2 sec delay for autoFocus.
*/
//camera.autoFocus(autoFocusCallback);
focusHandler.postDelayed(doFocusRunnable, 2000);
}
}
} catch (Exception e) {
logger.error("Error while setting AutoFocus in Camera."+e);
}
}
private boolean isFlashSupported(Camera.Parameters params) {
if (params != null) {
List<String> flashModes = params.getSupportedFlashModes();
if(flashModes == null) {
return false;
}
for(String flashMode : flashModes) {
if(Camera.Parameters.FLASH_MODE_ON.equals(flashMode)) {
return true;
}
}
}
return false;
}
#Override
protected void onStop() {
super.onStop();
if (editableCapturedImageview != null) {
editableCapturedImageview.resetCanvas();
}
}
}
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private static Logger logger = LoggerFactory.getLogger(CameraPreview.class);
private SurfaceHolder surfaceHolder;
private Camera camera;
private List<Size> cameraSizeList;
private Camera.Parameters cameraParameters;
public static boolean isCameraPreviewStarted = false;
public CameraPreview(Context context, Camera camera) {
super(context);
logger.info("Inside CameraPreview(Context context, Camera camera)");
this.camera = camera;
isCameraPreviewStarted = false;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
surfaceHolder = getHolder();
surfaceHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
try {
if (camera != null) {
logger.info("Camera Surface has been created, now tell the camera where to draw the preview.");
camera.setPreviewDisplay(holder);
camera.startPreview();
isCameraPreviewStarted = true;
}
} catch (IOException e) {
logger.error("Error occured in surfaceCreated.", e);
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
logger.info("Camera SurfaceView Destroyed.");
isCameraPreviewStarted = false;
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if (surfaceHolder.getSurface() == null) {
if (logger.isDebugEnabled()) {
logger.debug("onsurfaceChanged : preview surface does not exist");
}
return;
}
try {
if (logger.isDebugEnabled()) {
logger.debug("onsurfaceChanged :stop preview before making resize/rotate/reformatting changes");
}
isCameraPreviewStarted = false;
camera.stopPreview();
} catch (Exception e) {
logger.error("onsurfaceChanged :Ignored surfaceChanged because tried to stop a non-existent preview", e);
}
if (camera != null) {
cameraParameters = camera.getParameters();
cameraSizeList = cameraParameters.getSupportedPreviewSizes();
cameraParameters.setPreviewSize(getMaxSupportedVideoSize().width, getMaxSupportedVideoSize().height);
surfaceHolder.setFixedSize(getMaxSupportedVideoSize().width, getMaxSupportedVideoSize().height);
camera.setParameters(cameraParameters);
if (logger.isDebugEnabled()) {
logger.debug("onsurfaceChanged : made resize/rotate/reformatting changes:preview size:"
+ String.valueOf(getMaxSupportedVideoSize().width) + ":"
+ String.valueOf(getMaxSupportedVideoSize().height));
}
}
try {
if (logger.isDebugEnabled()) {
logger.debug("onsurfaceChanged :start preview with new settings");
}
if (camera != null) {
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
logger.info("onsurfaceChanged :start preview with new settings");
isCameraPreviewStarted = true;
}
} catch (Exception e) {
logger.error("onsurfaceChanged :Error while resetting camera preview on surfaceChanged.", e);
}
}
public Size getMaxSupportedVideoSize() {
int maximum = cameraSizeList.get(0).width;
int position = 0;
for (int i = 0; i < cameraSizeList.size() - 1; i++) {
if (cameraSizeList.get(i).width > maximum) {
maximum = cameraSizeList.get(i).width; // new maximum
position = i - 1;
}
}
if (position == 0) {
int secondMax = cameraSizeList.get(1).width;
position = 1;
for (int j = 1; j < cameraSizeList.size() - 1; j++) {
if (cameraSizeList.get(j).width > secondMax) {
secondMax = cameraSizeList.get(j).width; // new maximum
position = j;
}
}
}
return cameraSizeList.get(position);
}
}

Android OpenCv Utils: nMatToBitmap catched cv::Exception:

I already created camera view with portrait mode and its working perfectly, but now I am trying to apply face detection which is working in landscape mode but not in portrait mode, check out error below.
E/OpenCV/StaticHelper: OpenCV error: Cannot load info library for OpenCV
E/cv::error(): OpenCV Error: Assertion failed (src.dims == 2 && info.height == (uint32_t)src.rows && info.width == (uint32_t)src.cols) in void Java_org_opencv_android_Utils_nMatToBitmap2(JNIEnv*, jclass, jlong, jobject, jboolean), file /Volumes/Linux/builds/master_pack-android/opencv/modules/java/generator/src/cpp/utils.cpp, line 97
E/org.opencv.android.Utils: nMatToBitmap catched cv::Exception: /Volumes/Linux/builds/master_pack-android/opencv/modules/java/generator/src/cpp/utils.cpp:97: error: (-215) src.dims == 2 && info.height == (uint32_t)src.rows && info.width == (uint32_t)src.cols in function void Java_org_opencv_android_Utils_nMatToBitmap2(JNIEnv*, jclass, jlong, jobject, jboolean)
E/CameraBridge: Mat type: Mat [ 0*0*CV_8UC4, isCont=true, isSubmat=false, nativeObj=0xffffffffb80ebf00, dataAddr=0x0 ]E/CameraBridge: Bitmap type: 480*720
E/CameraBridge: Utils.matToBitmap() throws an exception: /Volumes/Linux/builds/master_pack-android/opencv/modules/java/generator/src/cpp/utils.cpp:97: error: (-215) src.dims == 2 && info.height == (uint32_t)src.rows && info.width == (uint32_t)src.cols in function void Java_org_opencv_android_Utils_nMatToBitmap2(JNIEnv*, jclass, jlong, jobject, jboolean)
My Camera class is as follows to show camera frames in portrait view
public class PortraitCameraView extends CameraBridgeViewBase implements Camera.PreviewCallback {
private static final int MAGIC_TEXTURE_ID = 10;
private static final String TAG = "JavaCameraView";
private byte mBuffer[];
private Mat[] mFrameChain;
private int mChainIdx = 0;
private Thread mThread;
private boolean mStopThread;
protected Camera mCamera;
protected JavaCameraFrame[] mCameraFrame;
private SurfaceTexture mSurfaceTexture;
private int mCameraId;
public static class JavaCameraSizeAccessor implements ListItemAccessor {
public int getWidth(Object obj) {
Camera.Size size = (Camera.Size) obj;
return size.width;
}
public int getHeight(Object obj) {
Camera.Size size = (Camera.Size) obj;
return size.height;
}
}
public PortraitCameraView(Context context, int cameraId) {
super(context, cameraId);
}
public PortraitCameraView(Context context, AttributeSet attrs) {
super(context, attrs);
}
protected boolean initializeCamera(int width, int height) {
Log.d(TAG, "Initialize java camera");
boolean result = true;
synchronized (this) {
mCamera = null;
boolean connected = false;
int numberOfCameras = android.hardware.Camera.getNumberOfCameras();
android.hardware.Camera.CameraInfo cameraInfo = new android.hardware.Camera.CameraInfo();
for (int i = 0; i < numberOfCameras; i++) {
android.hardware.Camera.getCameraInfo(i, cameraInfo);
if (cameraInfo.facing == android.hardware.Camera.CameraInfo.CAMERA_FACING_BACK) {
try {
mCamera = Camera.open(i);
mCameraId = i;
connected = true;
} catch (RuntimeException e) {
Log.e(TAG, "Camera #" + i + "failed to open: " + e.getMessage());
}
if (connected) break;
}
}
if (mCamera == null) return false;
/* Now set camera parameters */
try {
Camera.Parameters params = mCamera.getParameters();
Log.d(TAG, "getSupportedPreviewSizes()");
List<Camera.Size> sizes = params.getSupportedPreviewSizes();
if (sizes != null) {
/* Select the size that fits surface considering maximum size allowed */
Size frameSize = calculateCameraFrameSize(sizes, new JavaCameraSizeAccessor(), height, width); //use turn around values here to get the correct prev size for portrait mode
params.setPreviewFormat(ImageFormat.NV21);
Log.d(TAG, "Set preview size to " + Integer.valueOf((int)frameSize.width) + "x" + Integer.valueOf((int)frameSize.height));
params.setPreviewSize((int)frameSize.width, (int)frameSize.height);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
params.setRecordingHint(true);
List<String> FocusModes = params.getSupportedFocusModes();
if (FocusModes != null && FocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO))
{
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
}
mCamera.setParameters(params);
params = mCamera.getParameters();
mFrameWidth = params.getPreviewSize().height; //the frame width and height of the super class are used to generate the cached bitmap and they need to be the size of the resulting frame
mFrameHeight = params.getPreviewSize().width;
int realWidth = mFrameHeight; //the real width and height are the width and height of the frame received in onPreviewFrame
int realHeight = mFrameWidth;
if ((getLayoutParams().width == FrameLayout.LayoutParams.MATCH_PARENT) && (getLayoutParams().height == FrameLayout.LayoutParams.MATCH_PARENT))
mScale = Math.min(((float)height)/mFrameHeight, ((float)width)/mFrameWidth);
else
mScale = 0;
if (mFpsMeter != null) {
mFpsMeter.setResolution(mFrameWidth, mFrameHeight);
}
int size = mFrameWidth * mFrameHeight;
size = size * ImageFormat.getBitsPerPixel(params.getPreviewFormat()) / 8;
mBuffer = new byte[size];
mCamera.addCallbackBuffer(mBuffer);
mCamera.setPreviewCallbackWithBuffer(this);
mFrameChain = new Mat[2];
mFrameChain[0] = new Mat(realHeight + (realHeight/2), realWidth, CvType.CV_8UC1); //the frame chane is still in landscape
mFrameChain[1] = new Mat(realHeight + (realHeight/2), realWidth, CvType.CV_8UC1);
AllocateCache();
mCameraFrame = new JavaCameraFrame[2];
mCameraFrame[0] = new JavaCameraFrame(mFrameChain[0], mFrameWidth, mFrameHeight); //the camera frame is in portrait
mCameraFrame[1] = new JavaCameraFrame(mFrameChain[1], mFrameWidth, mFrameHeight);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
mSurfaceTexture = new SurfaceTexture(MAGIC_TEXTURE_ID);
mCamera.setPreviewTexture(mSurfaceTexture);
} else
mCamera.setPreviewDisplay(null);
/* Finally we are ready to start the preview */
Log.d(TAG, "startPreview");
mCamera.startPreview();
}
else
result = false;
} catch (Exception e) {
result = false;
e.printStackTrace();
}
}
return result;
}
protected void releaseCamera() {
synchronized (this) {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.setPreviewCallback(null);
mCamera.release();
}
mCamera = null;
if (mFrameChain != null) {
mFrameChain[0].release();
mFrameChain[1].release();
}
if (mCameraFrame != null) {
mCameraFrame[0].release();
mCameraFrame[1].release();
}
}
}
#Override
protected boolean connectCamera(int width, int height) {
/* 1. We need to instantiate camera
* 2. We need to start thread which will be getting frames
*/
/* First step - initialize camera connection */
Log.d(TAG, "Connecting to camera");
if (!initializeCamera(width, height))
return false;
/* now we can start update thread */
Log.d(TAG, "Starting processing thread");
mStopThread = false;
mThread = new Thread(new CameraWorker());
mThread.start();
return true;
}
protected void disconnectCamera() {
/* 1. We need to stop thread which updating the frames
* 2. Stop camera and release it
*/
Log.d(TAG, "Disconnecting from camera");
try {
mStopThread = true;
Log.d(TAG, "Notify thread");
synchronized (this) {
this.notify();
}
Log.d(TAG, "Wating for thread");
if (mThread != null)
mThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
mThread = null;
}
/* Now release camera */
releaseCamera();
}
public void onPreviewFrame(byte[] frame, Camera arg1) {
Log.d(TAG, "Preview Frame received. Frame size: " + frame.length);
synchronized (this) {
mFrameChain[1 - mChainIdx].put(0, 0, frame);
this.notify();
}
if (mCamera != null)
mCamera.addCallbackBuffer(mBuffer);
}
private class JavaCameraFrame implements CvCameraViewFrame {
private Mat mYuvFrameData;
private Mat mRgba;
private int mWidth;
private int mHeight;
private Mat mRotated;
public Mat gray() {
if (mRotated != null) mRotated.release();
mRotated = mYuvFrameData.submat(0, mWidth, 0, mHeight); //submat with reversed width and height because its done on the landscape frame
mRotated = mRotated.t();
Core.flip(mRotated, mRotated, 1);
return mRotated;
}
public Mat rgba() {
Imgproc.cvtColor(mYuvFrameData, mRgba, Imgproc.COLOR_YUV2BGR_NV12, 4);
if (mRotated != null) mRotated.release();
mRotated = mRgba.t();
Core.flip(mRotated, mRotated, 1);
return mRotated;
}
public JavaCameraFrame(Mat Yuv420sp, int width, int height) {
super();
mWidth = width;
mHeight = height;
mYuvFrameData = Yuv420sp;
mRgba = new Mat();
}
public void release() {
mRgba.release();
if (mRotated != null) mRotated.release();
}
};
private class CameraWorker implements Runnable {
public void run() {
do {
synchronized (PortraitCameraView.this) {
try {
PortraitCameraView.this.wait();
} catch (InterruptedException e) {
Log.e(TAG, "CameraWorker interrupted", e);
}
}
if (!mStopThread) {
if (!mFrameChain[mChainIdx].empty())
deliverAndDrawFrame(mCameraFrame[mChainIdx]);
mChainIdx = 1 - mChainIdx;
}
} while (!mStopThread);
Log.d(TAG, "Finish processing thread");
}
}
}
OnCameraFrame method is as bellow.
#Override
public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
mRgba = inputFrame.rgba();
mGray = inputFrame.gray();
if (mAbsoluteFaceSize == 0) {
int height = mGray.rows();
if (Math.round(height * mRelativeFaceSize) > 0) {
mAbsoluteFaceSize = Math.round(height * mRelativeFaceSize);
}
mNativeDetector.setMinFaceSize(mAbsoluteFaceSize);
}
MatOfRect faces = new MatOfRect();
if (mDetectorType == JAVA_DETECTOR) {
if (mJavaDetector != null)
mJavaDetector.detectMultiScale(mGray, faces, 1.1, 2, 2, // TODO: objdetect.CV_HAAR_SCALE_IMAGE
new Size(mAbsoluteFaceSize, mAbsoluteFaceSize), new Size());
}
else if (mDetectorType == NATIVE_DETECTOR) {
if (mNativeDetector != null)
mNativeDetector.detect(mGray, faces);
}
else {
Log.e(TAG, "Detection method is not selected!");
}
Rect[] facesArray = faces.toArray();
for (int i = 0; i < facesArray.length; i++)
Imgproc.rectangle(mRgba, facesArray[i].tl(), facesArray[i].br(), FACE_RECT_COLOR, 3);
return mRgba;
}
I'm sure this is too late, given that the question's a month old, but the answer (amazingly) is that OpenCV/JavaCameraView does not support portrait mode, only landscape.
Freaky, right? Struggled with this myself for days, but then figured out that JavaCameraView can't do portrait. There are some bend-over-backwards hacks out there to create a de facto portrait mode (involved flipping the image Mat), but I didn't think the results were worth the effort. I just force the view to show landscape all the time using a directive in the AndroidManifest.xml file.
android:screenOrientation="landscape"
android:theme="#style/Theme.AppCompat.NoActionBar"
http://answers.opencv.org/question/95248/changing-opencv-camera-view-orientation-on-androi/

Camera Preview performance issue on some devices

I am creating a camera application using android camera api by this example: https://examples.javacodegeeks.com/android/core/hardware/camera-hardware/android-camera-example/
I made some changes according to my needs and you can see the code below. The problem is, camera preview for back camera works quite fine on my LG G3 device but on LG G4 it gets too slow. It also works fine with front camera on both devices.
What can cause this problem ?
CameraPreview:
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback{
private static String TAG = "CameraPreview";
private SurfaceHolder mHolder;
private Camera mCamera;
private List<Size> mSupportedPreviewSizes;
private Size mPreviewSize;
public CameraPreview(Context context, Camera camera){
super(context);
mCamera = camera;
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
try{
Log.d(TAG, "Surface Created..");
if(mCamera == null){
mCamera.setPreviewDisplay(surfaceHolder);
mCamera.setDisplayOrientation(90);
mCamera.startPreview();
}
} catch (IOException e) {
Log.d(VIEW_LOG_TAG, "Error setting camera preview: " + e.getMessage());
}
}
public void refreshCamera(Camera camera) {
if (mHolder.getSurface() == null) {
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e) {
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings
setCamera(camera);
try {
Log.d(TAG,"RefreshCamera..");
if(mCamera == null){
Log.d(TAG,"Camera null");
}
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
mCamera.setParameters(parameters);
mCamera.setPreviewDisplay(mHolder);
mCamera.setPreviewDisplay(mHolder);
mCamera.setDisplayOrientation(90);
mCamera.startPreview();
} catch (Exception e) {
Log.d(VIEW_LOG_TAG, "Error starting camera preview: " + e.getMessage());
}
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
Log.d(TAG, "Surface Changed..");
refreshCamera(mCamera);
}
public void setCamera(Camera camera) {
//method to set a camera instance
mCamera = camera;
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
mCamera.release();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Log.d(TAG,"onMeasure..");
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(width, height);
if(mSupportedPreviewSizes==null){
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
}else{
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
Log.d(TAG, "mPreviewSize set.. Width: " + mPreviewSize.width+" Height: " + mPreviewSize.height);
}
}
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio=(double)h / w;
if (sizes == null) return null;
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
for (Camera.Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
}
I can share the Activity class if its needed..
Thanks..
I had the same problem using surface view .use the below preview class.its working for me for all the device screen.
public class SquareCameraPreview extends SurfaceView {
public static final String TAG = SquareCameraPreview.class.getSimpleName();
private static final int INVALID_POINTER_ID = -1;
private static final int ZOOM_OUT = 0;
private static final int ZOOM_IN = 1;
private static final int ZOOM_DELTA = 1;
private static final int FOCUS_SQR_SIZE = 100;
private static final int FOCUS_MAX_BOUND = 1000;
private static final int FOCUS_MIN_BOUND = -FOCUS_MAX_BOUND;
private static final double ASPECT_RATIO = 3.0 / 4.0;
private Camera mCamera;
private float mLastTouchX;
private float mLastTouchY;
// For scaling
private int mMaxZoom;
private boolean mIsZoomSupported;
private int mActivePointerId = INVALID_POINTER_ID;
private int mScaleFactor = 1;
private ScaleGestureDetector mScaleDetector;
// For focus
private boolean mIsFocus;
private boolean mIsFocusReady;
private Camera.Area mFocusArea;
private ArrayList<Camera.Area> mFocusAreas;
public SquareCameraPreview(Context context) {
super(context);
init(context);
}
public SquareCameraPreview(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public SquareCameraPreview(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
private void init(Context context) {
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
mFocusArea = new Camera.Area(new Rect(), 1000);
mFocusAreas = new ArrayList<Camera.Area>();
mFocusAreas.add(mFocusArea);
}
/**
* Measure the view and its content to determine the measured width and the
* measured height
*/
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int height = MeasureSpec.getSize(heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
final boolean isPortrait =
getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
if (isPortrait) {
if (width > height * ASPECT_RATIO) {
width = (int) (height * ASPECT_RATIO + 0.5);
} else {
height = (int) (width / ASPECT_RATIO + 0.5);
}
} else {
if (height > width * ASPECT_RATIO) {
height = (int) (width * ASPECT_RATIO + 0.5);
} else {
width = (int) (height / ASPECT_RATIO + 0.5);
}
}
setMeasuredDimension(width, height);
}
public int getViewWidth() {
return getWidth();
}
public int getViewHeight() {
return getHeight();
}
public void setCamera(Camera camera) {
mCamera = camera;
if (camera != null) {
Camera.Parameters params = camera.getParameters();
mIsZoomSupported = params.isZoomSupported();
if (mIsZoomSupported) {
mMaxZoom = params.getMaxZoom();
}
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
mScaleDetector.onTouchEvent(event);
final int action = event.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
mIsFocus = true;
mLastTouchX = event.getX();
mLastTouchY = event.getY();
mActivePointerId = event.getPointerId(0);
break;
}
case MotionEvent.ACTION_UP: {
if (mIsFocus && mIsFocusReady) {
handleFocus(mCamera.getParameters());
}
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_POINTER_DOWN: {
mCamera.cancelAutoFocus();
mIsFocus = false;
break;
}
case MotionEvent.ACTION_CANCEL: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
}
return true;
}
private void handleZoom(Camera.Parameters params) {
int zoom = params.getZoom();
if (mScaleFactor == ZOOM_IN) {
if (zoom < mMaxZoom) zoom += ZOOM_DELTA;
} else if (mScaleFactor == ZOOM_OUT) {
if (zoom > 0) zoom -= ZOOM_DELTA;
}
params.setZoom(zoom);
mCamera.setParameters(params);
}
private void handleFocus(Camera.Parameters params) {
float x = mLastTouchX;
float y = mLastTouchY;
if (!setFocusBound(x, y)) return;
List<String> supportedFocusModes = params.getSupportedFocusModes();
if (supportedFocusModes != null
&& supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
Log.d(TAG, mFocusAreas.size() + "");
params.setFocusAreas(mFocusAreas);
params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
mCamera.setParameters(params);
mCamera.autoFocus(new Camera.AutoFocusCallback() {
#Override
public void onAutoFocus(boolean success, Camera camera) {
// Callback when the auto focus completes
}
});
}
}
public void setIsFocusReady(final boolean isFocusReady) {
mIsFocusReady = isFocusReady;
}
private boolean setFocusBound(float x, float y) {
int left = (int) (x - FOCUS_SQR_SIZE / 2);
int right = (int) (x + FOCUS_SQR_SIZE / 2);
int top = (int) (y - FOCUS_SQR_SIZE / 2);
int bottom = (int) (y + FOCUS_SQR_SIZE / 2);
if (FOCUS_MIN_BOUND > left || left > FOCUS_MAX_BOUND) return false;
if (FOCUS_MIN_BOUND > right || right > FOCUS_MAX_BOUND) return false;
if (FOCUS_MIN_BOUND > top || top > FOCUS_MAX_BOUND) return false;
if (FOCUS_MIN_BOUND > bottom || bottom > FOCUS_MAX_BOUND) return false;
mFocusArea.rect.set(left, top, right, bottom);
return true;
}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
#Override
public boolean onScale(ScaleGestureDetector detector) {
mScaleFactor = (int) detector.getScaleFactor();
handleZoom(mCamera.getParameters());
return true;
}
}
}
public class CameraFragment extends Fragment implements SurfaceHolder.Callback, Camera.PictureCallback {
public static int HIGH_RESOLUTION_WIDTH=1000;
public static int HIGH_RESOLUTION_HIGHT=1500;
public static String clorie_count;
private long startTime = 0L;
public static final String TAG = CameraFragment.class.getSimpleName();
public static final String CAMERA_ID_KEY = "camera_id";
public static final String CAMERA_FLASH_KEY = "flash_mode";
public static final String IMAGE_INFO = "image_info";
private static final int PICTURE_SIZE_MAX_WIDTH = 1280;
private static final int PREVIEW_SIZE_MAX_WIDTH = 640;
private int mCameraID;
private String mFlashMode;
private Camera mCamera;
private SquareCameraPreview mPreviewView;
private SurfaceHolder mSurfaceHolder;
private boolean mIsSafeToTakePhoto = false;
private ImageParameters mImageParameters;
private CameraOrientationListener mOrientationListener;
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
context = activity;
mOrientationListener = new CameraOrientationListener(context);
}
View view;
Dialog listDialog;
#SuppressLint("NewApi")
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.camera_fragment, container, false);
if (savedInstanceState == null) {
mCameraID = getBackCameraID();
mFlashMode = CameraSettingPreferences.getCameraFlashMode(getActivity());
mImageParameters = new ImageParameters();
} else {
mCameraID = savedInstanceState.getInt(CAMERA_ID_KEY);
mFlashMode = savedInstanceState.getString(CAMERA_FLASH_KEY);
mImageParameters = savedInstanceState.getParcelable(IMAGE_INFO);
}
mPreviewView = (SquareCameraPreview) view.findViewById(R.id.camerapreview);
mPreviewView.getHolder().addCallback(CameraFragment.this);
mImageParameters.mIsPortrait =getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
capture_icon.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
takePicture();
}
});
return view;
}
private void takePicture() {
if (mIsSafeToTakePhoto) {
setSafeToTakePhoto(false);
mOrientationListener.rememberOrientation();
// Shutter callback occurs after the image is captured. This can
// be used to trigger a sound to let the user know that image is taken
Camera.ShutterCallback shutterCallback = null;
// Raw callback occurs when the raw image data is available
Camera.PictureCallback raw = null;
// postView callback occurs when a scaled, fully processed
// postView image is available.
Camera.PictureCallback postView = null;
// jpeg callback occurs when the compressed image is available
mCamera.takePicture(shutterCallback, raw, postView, this);
}
}
private void setSafeToTakePhoto(final boolean isSafeToTakePhoto) {
mIsSafeToTakePhoto = isSafeToTakePhoto;
}
private void setCameraFocusReady(final boolean isFocusReady) {
if (this.mPreviewView != null) {
mPreviewView.setIsFocusReady(isFocusReady);
}
}
/**
* Determine the current display orientation and rotate the camera preview
* accordingly
*/
private void determineDisplayOrientation() {
CameraInfo cameraInfo = new CameraInfo();
Camera.getCameraInfo(mCameraID, cameraInfo);
// Clockwise rotation needed to align the window display to the natural position
int rotation = getActivity().getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0: {
degrees = 0;
break;
}
case Surface.ROTATION_90: {
degrees = 90;
break;
}
case Surface.ROTATION_180: {
degrees = 180;
break;
}
case Surface.ROTATION_270: {
degrees = 270;
break;
}
}
int displayOrientation;
// CameraInfo.Orientation is the angle relative to the natural position of the device
// in clockwise rotation (angle that is rotated clockwise from the natural position)
if (cameraInfo.facing == CameraInfo.CAMERA_FACING_FRONT) {
// Orientation is angle of rotation when facing the camera for
// the camera image to match the natural orientation of the device
displayOrientation = (cameraInfo.orientation + degrees) % 360;
displayOrientation = (360 - displayOrientation) % 360;
} else {
displayOrientation = (cameraInfo.orientation - degrees + 360) % 360;
}
mImageParameters.mDisplayOrientation = displayOrientation;
mImageParameters.mLayoutOrientation = degrees;
mCamera.setDisplayOrientation(mImageParameters.mDisplayOrientation);
}
private void setupCamera() {
// Never keep a global parameters
Camera.Parameters parameters = mCamera.getParameters();
Size bestPreviewSize = determineBestPreviewSize(parameters);
Size bestPictureSize = determineBestPictureSize(parameters);
parameters.setPreviewSize(bestPreviewSize.width, bestPreviewSize.height);
parameters.setPictureSize(bestPictureSize.width, bestPictureSize.height);
// Set continuous picture focus, if it's supported
if (parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
}
final View changeCameraFlashModeBtn = getView().findViewById(R.id.flash);
List<String> flashModes = parameters.getSupportedFlashModes();
if (flashModes != null && flashModes.contains(mFlashMode)) {
parameters.setFlashMode(mFlashMode);
changeCameraFlashModeBtn.setVisibility(View.VISIBLE);
} else {
changeCameraFlashModeBtn.setVisibility(View.INVISIBLE);
}
// Lock in the changes
mCamera.setParameters(parameters);
}
private Size determineBestPreviewSize(Camera.Parameters parameters) {
return determineBestSize(parameters.getSupportedPreviewSizes(), PREVIEW_SIZE_MAX_WIDTH);
}
private Size determineBestPictureSize(Camera.Parameters parameters) {
return determineBestSize(parameters.getSupportedPictureSizes(), PICTURE_SIZE_MAX_WIDTH);
}
private Size determineBestSize(List<Size> sizes, int widthThreshold) {
Size bestSize = null;
Size size;
int numOfSizes = sizes.size();
for (int i = 0; i < numOfSizes; i++) {
size = sizes.get(i);
boolean isDesireRatio = (size.width / 4) == (size.height / 3);
boolean isBetterSize = (bestSize == null) || size.width > bestSize.width;
if (isDesireRatio && isBetterSize) {
bestSize = size;
}
}
if (bestSize == null) {
Log.d(TAG, "cannot find the best camera size");
return sizes.get(sizes.size() - 1);
}
return bestSize;
}
/**
* Start the camera preview
*/
private void startCameraPreview() {
determineDisplayOrientation();
setupCamera();
try {
mCamera.setPreviewDisplay(mSurfaceHolder);
mCamera.startPreview();
setSafeToTakePhoto(true);
setCameraFocusReady(true);
} catch (IOException e) {
Log.d(TAG, "Can't start camera preview due to IOException " + e);
e.printStackTrace();
}
}
private void getCamera(int cameraID) {
try {
mCamera = Camera.open(cameraID);
mPreviewView.setCamera(mCamera);
} catch (Exception e) {
Log.d(TAG, "Can't open camera with id " + cameraID);
e.printStackTrace();
}
}
#Override
public void onPictureTaken(byte[] arg0, Camera arg1) {
// TODO Auto-generated method stub
HERE YOU GET THE PHOTO BYTE[] arg0
CONVERT IT TO BITMAP OR STROE INTO A FILE
}
#Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2,
int arg3) {
// TODO Auto-generated method stub
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
mSurfaceHolder = holder;
getCamera(mCameraID);
startCameraPreview();
}
#Override
public void surfaceDestroyed(SurfaceHolder arg0) {
// TODO Auto-generated method stub
}
private static class CameraOrientationListener extends OrientationEventListener {
private int mCurrentNormalizedOrientation;
private int mRememberedNormalOrientation;
public CameraOrientationListener(Context context) {
super(context, SensorManager.SENSOR_DELAY_NORMAL);
}
#Override
public void onOrientationChanged(int orientation) {
if (orientation != ORIENTATION_UNKNOWN) {
mCurrentNormalizedOrientation = normalize(orientation);
}
}
/**
* #param degrees Amount of clockwise rotation from the device's natural position
* #return Normalized degrees to just 0, 90, 180, 270
*/
private int normalize(int degrees) {
if (degrees > 315 || degrees <= 45) {
return 0;
}
if (degrees > 45 && degrees <= 135) {
return 90;
}
if (degrees > 135 && degrees <= 225) {
return 180;
}
if (degrees > 225 && degrees <= 315) {
return 270;
}
throw new RuntimeException("The physics as we know them are no more. Watch out for anomalies.");
}
public void rememberOrientation() {
mRememberedNormalOrientation = mCurrentNormalizedOrientation;
}
public int getRememberedNormalOrientation() {
rememberOrientation();
return mRememberedNormalOrientation;
}
}
/*#Override
public void onResume() {
super.onResume();
if (mCamera == null) {
restartPreview();
}
}*/
#Override
public void onStop() {
mOrientationListener.disable();
// stop the preview
if (mCamera != null) {
stopCameraPreview();
mCamera.release();
mCamera = null;
}
if (getKillStatus()) {
android.os.Process.killProcess(android.os.Process.myPid());
}
// CameraSettingPreferences.saveCameraFlashMode(getActivity(), mFlashMode);
super.onStop();
}
#Override
public void onResume() {
super.onResume();
/*if (camera != null) {
camera.stopPreview();
preview.setupCamera(null,isResolutionHigh);
camera.release();
camera = null;
}
int numCams = Camera.getNumberOfCameras();
if (numCams > 0) {
try {
camera = Camera.open(0);
camera.startPreview();
preview.setupCamera(camera,isResolutionHigh);
} catch (RuntimeException ex) {
// Toast.makeText(ctx, getString(R.string.camera_not_found),
// Toast.LENGTH_LONG).show();
}
}*/
if (mCamera == null) {
restartPreview();
}
}
private void restartPreview() {
if (mCamera != null) {
stopCameraPreview();
mCamera.release();
mCamera = null;
}
getCamera(mCameraID);
startCameraPreview();
}
/**
* Stop the camera preview
*/
private void stopCameraPreview() {
setSafeToTakePhoto(false);
setCameraFocusReady(false);
// Nulls out callbacks, stops face detection
mCamera.stopPreview();
mPreviewView.setCamera(null);
}
private int getBackCameraID() {
return CameraInfo.CAMERA_FACING_BACK;
}
}
AND YOUR XML FILE
<com.demo.camera.SquareCameraPreview
android:id="#+id/camerapreview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
ImageParameter Class
public class ImageParameters implements Parcelable {
public boolean mIsPortrait;
public int mDisplayOrientation;
public int mLayoutOrientation;
public int mCoverHeight, mCoverWidth;
public int mPreviewHeight, mPreviewWidth;
public ImageParameters(Parcel in) {
mIsPortrait = (in.readByte() == 1);
mDisplayOrientation = in.readInt();
mLayoutOrientation = in.readInt();
mCoverHeight = in.readInt();
mCoverWidth = in.readInt();
mPreviewHeight = in.readInt();
mPreviewWidth = in.readInt();
}
public ImageParameters() {}
public int calculateCoverWidthHeight() {
return Math.abs(mPreviewHeight - mPreviewWidth) / 2;
}
public int getAnimationParameter() {
return mIsPortrait ? mCoverHeight : mCoverWidth;
}
public boolean isPortrait() {
return mIsPortrait;
}
public ImageParameters createCopy() {
ImageParameters imageParameters = new ImageParameters();
imageParameters.mIsPortrait = mIsPortrait;
imageParameters.mDisplayOrientation = mDisplayOrientation;
imageParameters.mLayoutOrientation = mLayoutOrientation;
imageParameters.mCoverHeight = mCoverHeight;
imageParameters.mCoverWidth = mCoverWidth;
imageParameters.mPreviewHeight = mPreviewHeight;
imageParameters.mPreviewWidth = mPreviewWidth;
return imageParameters;
}
public String getStringValues() {
return "is Portrait: " + mIsPortrait + "," +
"\ncover height: " + mCoverHeight + " width: " + mCoverWidth
+ "\npreview height: " + mPreviewHeight + " width: " + mPreviewWidth;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeByte((byte) (mIsPortrait ? 1 : 0));
dest.writeInt(mDisplayOrientation);
dest.writeInt(mLayoutOrientation);
dest.writeInt(mCoverHeight);
dest.writeInt(mCoverWidth);
dest.writeInt(mPreviewHeight);
dest.writeInt(mPreviewWidth);
}
public static final Creator<ImageParameters> CREATOR = new Parcelable.Creator<ImageParameters>() {
#Override
public ImageParameters createFromParcel(Parcel source) {
return new ImageParameters(source);
}
#Override
public ImageParameters[] newArray(int size) {
return new ImageParameters[size];
}
};
}
Another class you need camera setting preference
public class CameraSettingPreferences {
private static final String FLASH_MODE = "squarecamera__flash_mode";
private static SharedPreferences getCameraSettingPreferences(#NonNull final Context context) {
return context.getSharedPreferences("com.desmond.squarecamera", Context.MODE_PRIVATE);
}
protected static void saveCameraFlashMode(#NonNull final Context context, #NonNull final String cameraFlashMode) {
final SharedPreferences preferences = getCameraSettingPreferences(context);
if (preferences != null) {
final SharedPreferences.Editor editor = preferences.edit();
editor.putString(FLASH_MODE, cameraFlashMode);
editor.apply();
}
}
public static String getCameraFlashMode(#NonNull final Context context) {
final SharedPreferences preferences = getCameraSettingPreferences(context);
if (preferences != null) {
return preferences.getString(FLASH_MODE, Camera.Parameters.FLASH_MODE_AUTO);
}
return Camera.Parameters.FLASH_MODE_AUTO;
}
}
Let me know if you have any doubts.

Camera Preview landscape view not fullscreen

I've searched stack exchange and google for a solution but I can't seem to find one that works. My camera preview works beautifully in portrait, but when the orientation switches to landscape, it is not full screen and is highly distorted. I'm also trying to implement this as a fragment
Here is my code
CameraFragment.java
public class CameraFragment extends Fragment implements SurfaceHolder.Callback, Camera.PictureCallback {
public static final String TAG = CameraFragment.class.getSimpleName();
private static final int PICTURE_SIZE_MAX_WIDTH = 1280;
private static final int PREVIEW_SIZE_MAX_WIDTH = 640;
private int cameraId;
private Camera camera;
private SurfaceHolder surfaceHolder;
private CameraFragmentListener listener;
private int displayOrientation;
private int layoutOrientation;
private CameraOrientationListener orientationListener;
#Override
public void onAttach(Activity activity){
super.onAttach(activity);
if(!(activity instanceof CameraFragmentListener)){
throw new IllegalArgumentException("Must implement CameraFragmentListener interface");
}
listener = (CameraFragmentListener)activity;
orientationListener = new CameraOrientationListener(activity);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
CameraPreview previewView = new CameraPreview(getActivity());
previewView.getHolder().addCallback(this);
return previewView;
}
#Override
public void onResume() {
super.onResume();
orientationListener.enable();
try {
camera = Camera.open(cameraId);
} catch (Exception exception) {
Log.e(TAG, "Can't open camera with id " + cameraId, exception);
listener.onCameraError();
return;
}
}
#Override
public void onPause() {
super.onPause();
orientationListener.disable();
if(camera != null) {
stopCameraPreview();
camera.release();
}
}
private synchronized void startCameraPreview() {
determineDisplayOrientation();
setupCamera();
try {
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
} catch (Exception exception) {
Log.e(TAG, "Can't start camera preview due to Exception", exception);
listener.onCameraError();
}
}
private synchronized void stopCameraPreview() {
try {
camera.stopPreview();
} catch (Exception exception) {
Log.i(TAG, "Exception during stopping camera preview");
}
}
public void determineDisplayOrientation() {
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
Camera.getCameraInfo(cameraId, cameraInfo);
int rotation = getActivity().getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0:
degrees = 0;
break;
case Surface.ROTATION_90:
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}
int displayOrientation;
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
displayOrientation = (cameraInfo.orientation + degrees) % 360;
displayOrientation = (360 - displayOrientation) % 360;
} else {
displayOrientation = (cameraInfo.orientation - degrees + 360) % 360;
}
this.displayOrientation = displayOrientation;
this.layoutOrientation = degrees;
camera.setDisplayOrientation(displayOrientation);
}
public void setupCamera() {
Camera.Parameters parameters = camera.getParameters();
Camera.Size bestPreviewSize = determineBestPreviewSize(parameters);
Camera.Size bestPictureSize = determineBestPictureSize(parameters);
parameters.setPreviewSize(bestPreviewSize.width, bestPreviewSize.height);
parameters.setPictureSize(bestPictureSize.width, bestPictureSize.height);
camera.setParameters(parameters);
}
private Camera.Size determineBestPreviewSize(Camera.Parameters parameters) {
List<Camera.Size> sizes = parameters.getSupportedPreviewSizes();
return determineBestSize(sizes, PREVIEW_SIZE_MAX_WIDTH);
}
private Camera.Size determineBestPictureSize(Camera.Parameters parameters) {
List<Camera.Size> sizes = parameters.getSupportedPictureSizes();
return determineBestSize(sizes, PICTURE_SIZE_MAX_WIDTH);
}
protected Camera.Size determineBestSize(List<Camera.Size> sizes, int widthThreshold) {
Camera.Size bestSize = null;
for (Camera.Size currentSize : sizes) {
boolean isDesiredRatio = (currentSize.width / 4) == (currentSize.height / 3);
boolean isBetterSize = (bestSize == null || currentSize.width > bestSize.width);
boolean isInBounds = currentSize.width <= PICTURE_SIZE_MAX_WIDTH;
if (isDesiredRatio && isInBounds && isBetterSize) {
bestSize = currentSize;
}
}
if (bestSize == null) {
listener.onCameraError();
return sizes.get(0);
}
return bestSize;
}
public void takePicture(){
orientationListener.rememberOrientation();
camera.takePicture(null, null, this);
}
#Override
public void onPictureTaken(byte[] data, Camera camera){
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
int rotation = (displayOrientation + orientationListener.getRememberedOrientation() + layoutOrientation) % 360;
if(rotation != 0){
Bitmap oldBitmap = bitmap;
Matrix matrix = new Matrix();
matrix.postRotate(rotation);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false);
oldBitmap.recycle();
}
listener.onPictureTaken(bitmap);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
this.surfaceHolder = holder;
startCameraPreview();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
//fragment handles release
}
}
CameraFragmentListener.java
public interface CameraFragmentListener {
public void onCameraError();
public void onPictureTaken(Bitmap bitmap);
}
CameraOrientationListener.java
public class CameraOrientationListener extends OrientationEventListener {
private int currentNormalizedOrientation;
private int rememberNormalizedOrientation;
public CameraOrientationListener (Context context){
super(context, SensorManager.SENSOR_DELAY_NORMAL);
}
#Override
public void onOrientationChanged(int orientation) {
if(orientation != ORIENTATION_UNKNOWN){
currentNormalizedOrientation = normalize(orientation);
}
}
private int normalize(int degrees){
if(degrees > 315 || degrees <= 45)
return 0;
if(degrees > 45 && degrees <= 135)
return 90;
if(degrees > 135 && degrees <= 225)
return 180;
if(degrees > 225 && degrees <= 315)
return 270;
throw new RuntimeException("Wrong bruh");
}
public void rememberOrientation(){
rememberNormalizedOrientation = currentNormalizedOrientation;
}
public int getRememberedOrientation(){
return rememberNormalizedOrientation;
}
}
CameraPreview.java
public class CameraPreview extends SurfaceView {
private static final double ASPECT_RATIO = 3.0 / 4.0;
public CameraPreview(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public CameraPreview(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CameraPreview(Context context) {
super(context);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int height = MeasureSpec.getSize(heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
if (width > height * ASPECT_RATIO) {
width = (int) (height * ASPECT_RATIO + .5);
} else {
height = (int) (width / ASPECT_RATIO + .5);
}
setMeasuredDimension(width, height);
}
}
CameraActivity.java
public class CameraActivity extends Activity implements CameraFragmentListener {
public static final String TAG = CameraActivity.class.getSimpleName();
private static final int PICTURE_QUALITY = 90;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
}
#Override
public void onCameraError(){
Toast.makeText(this, getString(R.string.toast_error_camera_preview), Toast.LENGTH_SHORT).show();
finish();
}
public void takePicture(View view){
view.setEnabled(false);
CameraFragment fragment = (CameraFragment)getFragmentManager().findFragmentById(R.id.camera_fragment);
fragment.takePicture();
}
public void onPictureTaken(Bitmap bitmap){
File mediaStorageDir = new File(
Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES
),
getString(R.string.app_name)
);
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
showSavingPictureErrorToast();
return;
}
}
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile = new File(
mediaStorageDir.getPath() + File.separator + "MUSTACHE_"+ timeStamp + ".jpg"
);
try {
FileOutputStream stream = new FileOutputStream(mediaFile);
bitmap.compress(CompressFormat.JPEG, PICTURE_QUALITY, stream);
} catch (IOException exception) {
showSavingPictureErrorToast();
Log.w(TAG, "IOException during saving bitmap", exception);
return;
}
MediaScannerConnection.scanFile(
this,
new String[] { mediaFile.toString() },
new String[] { "image/jpeg" },
null
);
Intent intent = new Intent(this, PhotoActivity.class);
intent.setData(Uri.fromFile(mediaFile));
startActivity(intent);
finish();
}
private void showSavingPictureErrorToast() {
Toast.makeText(this, getText(R.string.toast_error_save_picture), Toast.LENGTH_SHORT).show();
}
}
Sorry for the extremely long post, I just want to be as thorough as possible. Thanks in advance guys!
If you want your preview to be full screen, you should set the full screen flag in your activity before you call setContentView:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_camera);
}

How to Autocapture when motion detection in android?

Hi I need auto capture when picture motion in Android camera. I can capture image with user's permission, but I want app to capture image automatically whenever motion is detected. Please any one give idea.
private static final String TAG = "MotionDetectionActivity";
private static SurfaceView preview = null;
private static SurfaceHolder previewHolder = null;
private static Camera camera = null;
private static boolean inPreview = false;
private static long mReferenceTime = 0;
private static IMotionDetection detector = null;
private static volatile AtomicBoolean processing = new AtomicBoolean(false);
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
preview = (SurfaceView) findViewById(R.id.preview);
previewHolder = preview.getHolder();
previewHolder.addCallback(surfaceCallback);
previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
if (Preferences.USE_RGB) {
detector = new RgbMotionDetection();
} else if (Preferences.USE_LUMA) {
detector = new LumaMotionDetection();
} else {
// Using State based (aggregate map)
detector = new AggregateLumaMotionDetection();
}
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
/**
* {#inheritDoc}
*/
#Override
public void onPause() {
super.onPause();
camera.setPreviewCallback(null);
if (inPreview) camera.stopPreview();
inPreview = false;
camera.release();
camera = null;
}
/**
* {#inheritDoc}
*/
#Override
public void onResume() {
super.onResume();
camera = Camera.open();
}
private PreviewCallback previewCallback = new PreviewCallback() {
/**
* {#inheritDoc}
*/
#Override
public void onPreviewFrame(byte[] data, Camera cam) {
if (data == null) return;
Camera.Size size = cam.getParameters().getPreviewSize();
if (size == null) return;
if (!GlobalData.isPhoneInMotion()) {
DetectionThread thread = new DetectionThread(data, size.width, size.height);
thread.start();
}
}
};
private SurfaceHolder.Callback surfaceCallback = new SurfaceHolder.Callback() {
/**
* {#inheritDoc}
*/
#Override
public void surfaceCreated(SurfaceHolder holder) {
try {
camera.setPreviewDisplay(previewHolder);
camera.setPreviewCallback(previewCallback);
} catch (Throwable t) {
Log.e("PreviewDemo-surfaceCallback", "Exception in setPreviewDisplay()", t);
}
}
/**
* {#inheritDoc}
*/
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Camera.Parameters parameters = camera.getParameters();
Camera.Size size = getBestPreviewSize(width, height, parameters);
if (size != null) {
parameters.setPreviewSize(size.width, size.height);
Log.d(TAG, "Using width=" + size.width + " height=" + size.height);
}
camera.setParameters(parameters);
camera.startPreview();
inPreview = true;
}
/**
* {#inheritDoc}
*/
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// Ignore
}
};
private static Camera.Size getBestPreviewSize(int width, int height, Camera.Parameters parameters) {
Camera.Size result = null;
for (Camera.Size size : parameters.getSupportedPreviewSizes()) {
if (size.width <= width && size.height <= height) {
if (result == null) {
result = size;
} else {
int resultArea = result.width * result.height;
int newArea = size.width * size.height;
if (newArea > resultArea) result = size;
}
}
}
return result;
}
private static final class DetectionThread extends Thread {
private byte[] data;
private int width;
private int height;
public DetectionThread(byte[] data, int width, int height) {
this.data = data;
this.width = width;
this.height = height;
}
/**
* {#inheritDoc}
*/
#Override
public void run() {
if (!processing.compareAndSet(false, true)) return;
// Log.d(TAG, "BEGIN PROCESSING...");
try {
// Previous frame
int[] pre = null;
if (Preferences.SAVE_PREVIOUS) pre = detector.getPrevious();
// Current frame (with changes)
// long bConversion = System.currentTimeMillis();
int[] img = null;
if (Preferences.USE_RGB) {
img = ImageProcessing.decodeYUV420SPtoRGB(data, width, height);
} else {
img = ImageProcessing.decodeYUV420SPtoLuma(data, width, height);
}
// long aConversion = System.currentTimeMillis();
// Log.d(TAG, "Converstion="+(aConversion-bConversion));
// Current frame (without changes)
int[] org = null;
if (Preferences.SAVE_ORIGINAL && img != null) org = img.clone();
if (img != null && detector.detect(img, width, height)) {
// The delay is necessary to avoid taking a picture while in
// the
// middle of taking another. This problem can causes some
// phones
// to reboot.
long now = System.currentTimeMillis();
if (now > (mReferenceTime + Preferences.PICTURE_DELAY)) {
mReferenceTime = now;
Bitmap previous = null;
if (Preferences.SAVE_PREVIOUS && pre != null) {
if (Preferences.USE_RGB) previous = ImageProcessing.rgbToBitmap(pre, width, height);
else previous = ImageProcessing.lumaToGreyscale(pre, width, height);
}
Bitmap original = null;
if (Preferences.SAVE_ORIGINAL && org != null) {
if (Preferences.USE_RGB) original = ImageProcessing.rgbToBitmap(org, width, height);
else original = ImageProcessing.lumaToGreyscale(org, width, height);
}
Bitmap bitmap = null;
if (Preferences.SAVE_CHANGES) {
if (Preferences.USE_RGB) bitmap = ImageProcessing.rgbToBitmap(img, width, height);
else bitmap = ImageProcessing.lumaToGreyscale(img, width, height);
}
Log.i(TAG, "Saving.. previous=" + previous + " original=" + original + " bitmap=" + bitmap);
Looper.prepare();
new SavePhotoTask().execute(previous, original, bitmap);
} else {
Log.i(TAG, "Not taking picture because not enough time has passed since the creation of the Surface");
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
processing.set(false);
}
// Log.d(TAG, "END PROCESSING...");
processing.set(false);
}
};
private static final class SavePhotoTask extends AsyncTask<Bitmap, Integer, Integer> {
/**
* {#inheritDoc}
*/
#Override
protected Integer doInBackground(Bitmap... data) {
for (int i = 0; i < data.length; i++) {
Bitmap bitmap = data[i];
String name = String.valueOf(System.currentTimeMillis());
if (bitmap != null) save(name, bitmap);
}
return 1;
}
private void save(String name, Bitmap bitmap) {
File photo = new File(Environment.getExternalStorageDirectory(), name + ".jpg");
if (photo.exists()) photo.delete();
try {
FileOutputStream fos = new FileOutputStream(photo.getPath());
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.close();
} catch (java.io.IOException e) {
Log.e("PictureDemo", "Exception in photoCallback", e);
}
}
}
}

Categories

Resources