I want to capture a video always horizontally.
If the user rotates the phone, I want to capture the video horizontally.
I have one reference for that but I want to make it for my own with customization.
how can I implement this in a smooth way?
Try this
public static void setCameraDisplayOrientation(int phoneRotation, int cameraId, Camera camera) {
Camera.CameraInfo info = new Camera.CameraInfo();
info = Camera.getCameraInfo(cameraId, info);
int degrees = 0;
switch (phoneRotation) {
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 result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360;
} else {
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
}
when phoneRotation is
int phoneRotation = activity.getWindowManager().getDefaultDisplay().getRotation();
By the way this answer originally refactored from some answer in stackoverflow.
When I test my application on my Android One phone or Emulator itself everything is ok but with some other devices there is a problem.
Problem is, I basically send a camera intent, get the data from intent after user takes a photo and I set the pixels of an ImageView with whatever I get from the camera. With some devices (Samsung mostly) image is rotated, it's not shown as it's taken.
My app only works in portrait mode but user can also take photo in Landscape mode if he/she rotates the phone when taking the image.
Is there a way to detect the default angle that the device rotates the images and so I rotate the bitmap after taking the image?
Here is the code :
Sending intent :
File path = new File(getActivity().getFilesDir(), "map_roomie");
if (!path.exists()) path.mkdirs();
mFileName = createImageFileName();
File image = new File(path, mFileName);
Uri imageUri = FileProvider.getUriForFile(getActivity(), AddRoomFragment.CAPTURE_IMAGE_FILE_PROVIDER, image);
Intent imageCaptureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
imageCaptureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(imageCaptureIntent, AddRoomFragment.CAMERA_CAPTURE_IMAGE_REQUEST_CODE);
capturing intent on fragment
File path = new File(getActivity().getFilesDir(), "map_roomie");
if (!path.exists()) path.mkdirs();
File imageFile = new File(path, mFileName);
setBitmapOfImageView(mCurrentPhotoId, decodeAndReturnBitmap(imageFile.getAbsolutePath()));
helper functions :
public void setBitmapOfImageView(int photoId, Bitmap bitmap)
{
mPhotos[photoId].setImageBitmap(bitmap);
mPhotosState[photoId] = 1;
}
public Bitmap decodeAndReturnBitmap(String filePath)
{
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, o);
final int REQUIRED_SIZE = 512;
int widthTemp = o.outWidth, heightTemp = o.outHeight;
int scale = 1;
while (true) {
if (widthTemp < REQUIRED_SIZE && heightTemp < REQUIRED_SIZE) {
break;
}
widthTemp /= 2;
heightTemp /= 2;
scale *= 2;
}
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
return BitmapFactory.decodeFile(filePath, o2);
}
If you want to make the camera image show in the same orientation as the display, you can use the following code.
public static void setCameraDisplayOrientation(Activity activity,
int cameraId, android.hardware.Camera camera) {
android.hardware.Camera.CameraInfo info =
new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
int rotation = activity.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 result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
}
For further info, refer https://developer.android.com/reference/android/hardware/Camera.html#setDisplayOrientation(int)
This solution works properly for me.
public static void setCameraDisplayOrientation (Activity activity, int cameraId, android.hardware.Camera camera){
android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
int rotation = activity.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 result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
}
Please have a look -
private int getCameraId() {
int curCameraId = 0;
if (Camera.getNumberOfCameras() > 0) {
curCameraId = (curCameraId + 1) % Camera.getNumberOfCameras();
} else {
curCameraId = 0;
}
return curCameraId;
}
public void setCameraDisplayOrientation(Activity activity, int curCameraId) {
if (camera == null) {
try {
camera = Camera.open(curCameraId);
} catch (Exception e) {
}
}
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(curCameraId, info);
WindowManager winManager = (WindowManager) activity.getSystemService(Context.WINDOW_SERVICE);
int rotation = winManager.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 result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
}
I fixed the issue using an ExifInterface. But still it would be great if someone can shed some light on detecting default angle applied on images when taking a picture.
Here is the code :
public Bitmap decodeAndReturnBitmap(String filePath)
{
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, o);
final int REQUIRED_SIZE = 512;
int widthTemp = o.outWidth, heightTemp = o.outHeight;
int scale = 1;
while (true) {
if (widthTemp < REQUIRED_SIZE && heightTemp < REQUIRED_SIZE) {
break;
}
widthTemp /= 2;
heightTemp /= 2;
scale *= 2;
}
ExifInterface exifInterface = null;
try {
exifInterface = new ExifInterface(filePath);
} catch (IOException e) {
e.printStackTrace();
}
int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED);
Matrix matrix = new Matrix();
switch(orientation) {
case ExifInterface.ORIENTATION_ROTATE_90 :
matrix.setRotate(90.0f);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
matrix.setRotate(180.0f);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
matrix.setRotate(270.0f);
break;
}
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
Bitmap bitmap = BitmapFactory.decodeFile(filePath, o2);
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}
So after a while of messing with the camera, I've finally got the actual camera orientation working with this:
private void setCameraDisplayOrientation(Activity activity,
int cameraId, android.hardware.Camera camera) {
android.hardware.Camera.CameraInfo info =
new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
int rotation = activity.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 result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
}
However, the status bar (the thing at the top with time and network info) is still in landscape.
I've already included this:
android:screenOrientation="portrait"
in my AndroidManifest.xml
Any ideas on how to fix this?
If you know what you want to set your orientation as you can use setRequestedOrientation(int requestedOrientation) in your Activity
How to keep camera in portrait mode in all devices?
my app is above 2.2
I tried
public void setRotation(int rotation) {
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 result;
CameraInfo cameraInfo = new Camera.CameraInfo();
Camera.getCameraInfo(cameraId, cameraInfo);
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (cameraInfo.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (cameraInfo.orientation - degrees + 360) % 360;
}
mCamera.stopPreview();
mCamera.setDisplayOrientation(result);
mCamera.startPreview();
}
but samsung devices ignoring mCamera.setDisplayOrientation(90)
Edited:
devices I found ignoring this:
Galaxy y(GT-S5360)(Android 2.3.6)
Galaxy Ace(GT-S5830)(Android 2.6.3)
but Galaxy S2 and other higher phones working well.
You can try
public int getCorrectCameraOrientation(CameraInfo info, Camera camera) {
int rotation = context.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 result;
if(info.facing==Camera.CameraInfo.CAMERA_FACING_FRONT){
result = (info.orientation + degrees) % 360;
result = (360 – result) % 360;
}else{
result = (info.orientation – degrees + 360) % 360;
}
return result;
}
Use this method as
mCamera.setDisplayOrientation(getCorrectCameraOrientation(mCameraInfo, mCamera));
This is not enough for rotation handling, you need to do below step also
mCamera.getParameters().setRotation(getCorrectCameraOrientation(mCameraInfo, mCamera));
This question already has answers here:
Android Camera in Portrait on SurfaceView
(6 answers)
Closed 7 years ago.
Is it possible to open the Camera Intent in android in only portrait mode, that is even if the user flipped the device, the camera will still be in portrait mode,
I tried the following answer: Force Portrait Mode but didn't work, Thanks
Try it -
private void setCameraDisplayOrientation(Activity activity,
int cameraId, android.hardware.Camera camera) {
android.hardware.Camera.CameraInfo info =
new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
int rotation = activity.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 result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
}
private void initCamera() {
if(mCamera == null) {
mCamera = Camera.open();
setCameraDisplayOrientation(activity, CameraInfo.CAMERA_FACING_BACK, mCamera);
mCamera.unlock();
}
}