Android Camera Rotate

Android camera rotate

if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {
camera.setDisplayOrientation(90);
lp.height = previewSurfaceHeight;
lp.width = (int) (previewSurfaceHeight / aspect);
} else {
camera.setDisplayOrientation(0);
lp.width = previewSurfaceWidth;
lp.height = (int) (previewSurfaceWidth / aspect);
}

Android camera and portrait rotation

Since I didn't find any complete answer to my question, I post my solution.

1. Get photo from the camera

protected File pictureFromCamera;
protected Uri photoUri;
...
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null)
{
// Create the File where the photo should go
pictureFromCamera = generateFile();
if (pictureFromCamera != null)
{
String authority = BuildConfig.APPLICATION_ID + ".provider";
photoUri = FileProvider.getUriForFile(DermatoPhotoCollectionActivity.this, authority, pictureFromCamera);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
startActivityForResult(takePictureIntent, REQUEST_PHOTO_FROM_CAMERA);
}
}

2. Get orientation of the photo

Here is the code to get the orientation, it is inspired by this article. Be aware that this require a dependency :
compile "com.android.support:exifinterface:27.1.1"

Getting the orientation of the photo depends of the device and might not work on some device (for example it works fine on my Xperia but not on Android Emulator).

public static int getOrientation(Context context, Uri photoUri)
{
InputStream in = null;
int orientation = ExifInterface.ORIENTATION_NORMAL;
try
{
in = context.getContentResolver().openInputStream(photoUri);
if (in != null)
{
android.support.media.ExifInterface exifInterface = new android.support.media.ExifInterface(in);
orientation = exifInterface.getAttributeInt(android.support.media.ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
}
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
if (in != null)
{
try
{
in.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}

return orientation;
}

3. Rotate the picture if needed

I use asyncTask to rotate the photo

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (resultCode == RESULT_OK)
{
final String pathPhotoFromCamera = pictureFromCamera.getAbsolutePath();

final ProgressDialog progressDialog = createProgressDialog();
progressDialog.show();

int orientation = getOrientation(this, photoUri);
int rotationAngle = 0;

if (orientation != ExifInterface.ORIENTATION_NORMAL)
{
switch (orientation)
{
case ExifInterface.ORIENTATION_ROTATE_90:
rotationAngle = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotationAngle = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
rotationAngle = 270;
break;
}
}

AsyncTaskRotatePicture.AsyncTaskParams params = new AsyncTaskRotatePicture.AsyncTaskParams(pathPhotoFromCamera, rotationAngle);

AsyncTaskRotatePicture taskRotatePicture = new AsyncTaskRotatePicture(new CallBack()
{
@Override
public void onPostExecute()
{
progressDialog.dismiss();
}
});

taskRotatePicture.execute(params);
}
}

4. Finally the code that rotate the photo

The function overwrites the initial photo.

public static void rotatePhoto(String photoFilePath, int rotationAngle)
{
Bitmap bm = BitmapFactory.decodeFile(photoFilePath);
Matrix matrix = new Matrix();
matrix.setRotate(rotationAngle, (float) bm.getWidth() / 2, (float) bm.getHeight() / 2);
byte[] extractedBitmap = extractByteFromBitmap(Bitmap.createBitmap(bm, 0, 0, bm.getWidth() - 1, bm.getHeight() - 1, matrix, true));
saveBitmapOnSdcard(extractedBitmap, photoFilePath);
}

Photo rotated from camera (SAMSUNG device)

UPD 29.08.2018 I found that this method doesn't work with Samsung device based on Android 8+. I don't have Samsung s8 (for example) and can't understand why this again does not work there. If someone can test and check why this not work - let's try to fix this together.


I found how to fix: well it's really stupid and very hard for me.

First step get activity result

 @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CAMERA_REQUEST && resultCode == Activity.RESULT_OK) {

String _path = Environment.getExternalStorageDirectory() + File.separator + "TakenFromCamera.jpg";
String p1 = Environment.getExternalStorageDirectory().toString();
String fName = "/TakenFromCamera.jpg";
final int rotation = getImageOrientation(_path);
File file = resaveBitmap(p1, fName, rotation);
Bitmap mBitmap = BitmapFactory.decodeFile(_path);

Main steps it's getImageOrientation before changes in file.

  1. getImageOrientation (by path)
  2. resave file (if need send to server, if you need only for preview we can skip this step)
  3. get correct bitmap from file

For preview it's enough to perform only steps 1 and 3, and using this function - just rotate bitmap.

private Bitmap checkRotationFromCamera(Bitmap bitmap, String pathToFile, int rotate) {
Matrix matrix = new Matrix();
matrix.postRotate(rotate);
Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
return rotatedBitmap;
}

getImageOrientation

public static int getImageOrientation(String imagePath) {
int rotate = 0;
try {
ExifInterface exif = new ExifInterface(imagePath);
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_270:
rotate = 270;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotate = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_90:
rotate = 90;
break;
}
} catch (IOException e) {
e.printStackTrace();
}
return rotate;
}

and resaveBitmap if need

private File resaveBitmap(String path, String filename, int rotation) { //help for fix landscape photos
String extStorageDirectory = path;
OutputStream outStream = null;
File file = new File(filename);
if (file.exists()) {
file.delete();
file = new File(extStorageDirectory, filename);
}
try {
// make a new bitmap from your file
Bitmap bitmap = BitmapFactory.decodeFile(path + filename);
bitmap = checkRotationFromCamera(bitmap, path + filename, rotation);
bitmap = Bitmap.createScaledBitmap(bitmap, (int) ((float) bitmap.getWidth() * 0.3f), (int) ((float) bitmap.getHeight() * 0.3f), false);
bitmap = Utils.getCircleImage(bitmap);
outStream = new FileOutputStream(path + filename);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
outStream.flush();
outStream.close();
} catch (Exception e) {
e.printStackTrace();
}
return file;
}

Why does an image captured using camera intent gets rotated on some devices on Android?

Most phone cameras are landscape, meaning if you take the photo in portrait, the resulting photos will be rotated 90 degrees. In this case, the camera software should populate the Exif data with the orientation that the photo should be viewed in.

Note that the below solution depends on the camera software/device manufacturer populating the Exif data, so it will work in most cases, but it is not a 100% reliable solution.

ExifInterface ei = new ExifInterface(photoPath);
int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_UNDEFINED);

Bitmap rotatedBitmap = null;
switch(orientation) {

case ExifInterface.ORIENTATION_ROTATE_90:
rotatedBitmap = rotateImage(bitmap, 90);
break;

case ExifInterface.ORIENTATION_ROTATE_180:
rotatedBitmap = rotateImage(bitmap, 180);
break;

case ExifInterface.ORIENTATION_ROTATE_270:
rotatedBitmap = rotateImage(bitmap, 270);
break;

case ExifInterface.ORIENTATION_NORMAL:
default:
rotatedBitmap = bitmap;
}

Here is the rotateImage method:

public static Bitmap rotateImage(Bitmap source, float angle) {
Matrix matrix = new Matrix();
matrix.postRotate(angle);
return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(),
matrix, true);
}

Controlling the camera to take pictures in portrait doesn't rotate the final images

The problem is when I saved the image I didn't do well.

@Override
public void onPictureTaken(byte[] data, Camera camera) {

String timeStamp = new SimpleDateFormat( "yyyyMMdd_HHmmss").format( new Date( ));
output_file_name = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) + File.separator + timeStamp + ".jpeg";

File pictureFile = new File(output_file_name);
if (pictureFile.exists()) {
pictureFile.delete();
}

try {
FileOutputStream fos = new FileOutputStream(pictureFile);

Bitmap realImage = BitmapFactory.decodeByteArray(data, 0, data.length);

ExifInterface exif=new ExifInterface(pictureFile.toString());

Log.d("EXIF value", exif.getAttribute(ExifInterface.TAG_ORIENTATION));
if(exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("6")){
realImage= rotate(realImage, 90);
} else if(exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("8")){
realImage= rotate(realImage, 270);
} else if(exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("3")){
realImage= rotate(realImage, 180);
} else if(exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("0")){
realImage= rotate(realImage, 90);
}

boolean bo = realImage.compress(Bitmap.CompressFormat.JPEG, 100, fos);

fos.close();

((ImageView) findViewById(R.id.imageview)).setImageBitmap(realImage);

Log.d("Info", bo + "");

} catch (FileNotFoundException e) {
Log.d("Info", "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d("TAG", "Error accessing file: " + e.getMessage());
}
}

public static Bitmap rotate(Bitmap bitmap, int degree) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();

Matrix mtx = new Matrix();
// mtx.postRotate(degree);
mtx.setRotate(degree);

return Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true);
}

Android how to fix camera orientation

I found the solution here. Answer by @Ed Jellard.

i just have to add camera.setDisplayOrientation(90); on surfaceCreated(SurfaceHolder holder) method, now the display is on the right angle.

see the happy T-REX :)

Android - Camera preview is sideways

This issue appeared to start out as a bug with certain hardware see here but can be overcome by using the call to mCamera.setDisplayOrientation(degrees) available in API 8. So this is how I implement it:

public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {            
if (isPreviewRunning) {
mCamera.stopPreview();
}

Parameters parameters = mCamera.getParameters();
Display display = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay();

if(display.getRotation() == Surface.ROTATION_0) {
parameters.setPreviewSize(height, width);
mCamera.setDisplayOrientation(90);
}

if(display.getRotation() == Surface.ROTATION_90) {
parameters.setPreviewSize(width, height);
}

if(display.getRotation() == Surface.ROTATION_180) {
parameters.setPreviewSize(height, width);
}

if(display.getRotation() == Surface.ROTATION_270) {
parameters.setPreviewSize(width, height);
mCamera.setDisplayOrientation(180);
}

mCamera.setParameters(parameters);
previewCamera();
}

And the previewCamera method :

public void previewCamera() {
try {
mCamera.setPreviewDisplay(mSurfaceHolder);
mCamera.startPreview();
isPreviewRunning = true;
} catch(Exception e) {
Log.d(APP_CLASS, "Cannot start preview", e);
}
}

This was on an HTC Desire and I had to initially put in logging statements in each of the rotation checks to say what the rotation was and then debugged on the device and watched the logCat output while I rotated the device. For the HTC Desire, 0 was the phone as you would have expected (portrait), 90 degrees was turning the phone 90 degrees COUNTER-CLOCKWISE (I had assumed it would have been clockwise). In the code you'll see I didn't need to do any display rotation when the phone was at 90 or 180 degrees - the device seemed to handle this itself. Only one point not working properly: The 270 degree rotation is when you turn the device 90 degrees clockwise and the display rotation counters that ok but if you rotate the device 270 degrees counter-clockwise, it doesn't appear to compensate it properly.

P.S. Note the swapover of width and height in the appropriate rotations.

Camera automatically get rotated by 90 degree in portrait mode

On the surfaceView which holds the Camera instance, you have to implement few methods. one of them is surfaceChanged. in that method you should update the orientation as follow:

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {

...
this.setCameraDisplayOrientation(this.cameraId, this.mCamera);
...
}

And the implementation:

   /**
* Calling this method makes the camera image show in the same orientation as the display.
* NOTE: This method is not allowed to be called during preview.
*
* @param cameraId
* @param camera
*/
@SuppressLint("NewApi")
public void setCameraDisplayOrientation(int cameraId, android.hardware.Camera camera) {
int rotation = ((WindowManager)context.getSystemService(Context.WINDOW_SERVICE)).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 (Utils.hasGingerbread()) {
android.hardware.Camera.CameraInfo info =
new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
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;
}
} else {
// on API 8 and lower devices
if (context.getResources().getConfiguration().orientation !=Configuration.ORIENTATION_LANDSCAPE) {
result = 90;
} else {
result = 0;
}
}
try {
camera.setDisplayOrientation(result);
} catch (Exception e) {
// may fail on old OS versions. ignore it.
e.printStackTrace();
}
}

How to set Android camera orientation properly?

I finally fixed this using the Google's camera app. It gets the phone's orientation by using a sensor and then sets the EXIF tag appropriately. The JPEG which comes out of the camera is not oriented automatically.

Also, the camera preview works properly only in the landscape mode. If you need your activity layout to be oriented in portrait, you will have to do it manually using the value from the orientation sensor.



Related Topics



Leave a reply



Submit