Android Camera Setdisplayorientation(90) Fails In Different Devices
Solution 1:
Set orientation and preview in following different ways, use as requirement :
First Ways :
publicvoidsurfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
if (isPreviewRunning)
{
mCamera.stopPreview();
}
Parametersparameters= mCamera.getParameters();
Displaydisplay= ((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
publicvoidpreviewCamera()
{
try
{
mCamera.setPreviewDisplay(mSurfaceHolder);
mCamera.startPreview();
isPreviewRunning = true;
}
catch(Exception e)
{
Log.d(APP_CLASS, "Cannot start preview", e);
}
}
Second ways :
private Camera mCamera;
private OrientationEventListener mOrientationEventListener;
privateintmOrientation= -1;
privatestaticfinalintORIENTATION_PORTRAIT_NORMAL=1;
privatestaticfinalintORIENTATION_PORTRAIT_INVERTED=2;
privatestaticfinalintORIENTATION_LANDSCAPE_NORMAL=3;
privatestaticfinalintORIENTATION_LANDSCAPE_INVERTED=4;
@OverridepublicvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// force Landscape layout
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR | ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
/*
Your other initialization code here
*/
}
@OverrideprotectedvoidonResume() {
super.onResume();
if (mOrientationEventListener == null) {
mOrientationEventListener = newOrientationEventListener(this, SensorManager.SENSOR_DELAY_NORMAL) {
@OverridepublicvoidonOrientationChanged(int orientation) {
// determine our orientation based on sensor responseintlastOrientation= mOrientation;
if (orientation >= 315 || orientation < 45) {
if (mOrientation != ORIENTATION_PORTRAIT_NORMAL) {
mOrientation = ORIENTATION_PORTRAIT_NORMAL;
}
}
elseif (orientation < 315 && orientation >= 225) {
if (mOrientation != ORIENTATION_LANDSCAPE_NORMAL) {
mOrientation = ORIENTATION_LANDSCAPE_NORMAL;
}
}
elseif (orientation < 225 && orientation >= 135) {
if (mOrientation != ORIENTATION_PORTRAIT_INVERTED) {
mOrientation = ORIENTATION_PORTRAIT_INVERTED;
}
}
else { // orientation <135 && orientation > 45if (mOrientation != ORIENTATION_LANDSCAPE_INVERTED) {
mOrientation = ORIENTATION_LANDSCAPE_INVERTED;
}
}
if (lastOrientation != mOrientation) {
changeRotation(mOrientation, lastOrientation);
}
}
};
}
if (mOrientationEventListener.canDetectOrientation()) {
mOrientationEventListener.enable();
}
}
@OverrideprotectedvoidonPause() {
super.onPause();
mOrientationEventListener.disable();
}
/**
* Performs required action to accommodate new orientation
* @param orientation
* @param lastOrientation
*/privatevoidchangeRotation(int orientation, int lastOrientation) {
switch (orientation) {
case ORIENTATION_PORTRAIT_NORMAL:
mSnapButton.setImageDrawable(getRotatedImage(android.R.drawable.ic_menu_camera, 270));
mBackButton.setImageDrawable(getRotatedImage(android.R.drawable.ic_menu_revert, 270));
Log.v("CameraActivity", "Orientation = 90");
break;
case ORIENTATION_LANDSCAPE_NORMAL:
mSnapButton.setImageResource(android.R.drawable.ic_menu_camera);
mBackButton.setImageResource(android.R.drawable.ic_menu_revert);
Log.v("CameraActivity", "Orientation = 0");
break;
case ORIENTATION_PORTRAIT_INVERTED:
mSnapButton.setImageDrawable(getRotatedImage(android.R.drawable.ic_menu_camera, 90));
mBackButton.setImageDrawable(getRotatedImage(android.R.drawable.ic_menu_revert, 90));
Log.v("CameraActivity", "Orientation = 270");
break;
case ORIENTATION_LANDSCAPE_INVERTED:
mSnapButton.setImageDrawable(getRotatedImage(android.R.drawable.ic_menu_camera, 180));
mBackButton.setImageDrawable(getRotatedImage(android.R.drawable.ic_menu_revert, 180));
Log.v("CameraActivity", "Orientation = 180");
break;
}
}
/**
* Rotates given Drawable
* @param drawableId Drawable Id to rotate
* @param degrees Rotate drawable by Degrees
* @return Rotated Drawable
*/private Drawable getRotatedImage(int drawableId, int degrees) {
Bitmaporiginal= BitmapFactory.decodeResource(getResources(), drawableId);
Matrixmatrix=newMatrix();
matrix.postRotate(degrees);
Bitmaprotated= Bitmap.createBitmap(original, 0, 0, original.getWidth(), original.getHeight(), matrix, true);
returnnewBitmapDrawable(rotated);
}
And then in your PictureCallback set metadata to indicate rotation level:
private Camera.PictureCallbackmJpegCallback=newCamera.PictureCallback() {
@OverridepublicvoidonPictureTaken(byte[] data, Camera camera) {
try {
// Populate image metadataContentValuesimage=newContentValues();
// additional picture metadata
image.put(Media.DISPLAY_NAME, [picture name]);
image.put(Media.MIME_TYPE, "image/jpg");
image.put(Media.TITLE, [picture title]);
image.put(Media.DESCRIPTION, [picture description]);
image.put(Media.DATE_ADDED, [some time]);
image.put(Media.DATE_TAKEN, [some time]);
image.put(Media.DATE_MODIFIED, [some time]);
// do not rotate image, just put rotation info inswitch (mOrientation) {
case ORIENTATION_PORTRAIT_NORMAL:
image.put(Media.ORIENTATION, 90);
break;
case ORIENTATION_LANDSCAPE_NORMAL:
image.put(Media.ORIENTATION, 0);
break;
case ORIENTATION_PORTRAIT_INVERTED:
image.put(Media.ORIENTATION, 270);
break;
case ORIENTATION_LANDSCAPE_INVERTED:
image.put(Media.ORIENTATION, 180);
break;
}
// store the pictureUriuri= getContentResolver().insert(
Media.EXTERNAL_CONTENT_URI, image);
try {
Bitmapbitmap= BitmapFactory.decodeByteArray(data, 0,
data.length);
OutputStreamout= getContentResolver().openOutputStream(
uri);
booleansuccess= bitmap.compress(
Bitmap.CompressFormat.JPEG, 75, out);
out.close();
if (!success) {
finish(); // image output failed without any error,// silently finish
}
Now when landscape based devices are appearing an additional check for it is required in OrientationEventListener.
Displaydisplay= ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
if (display.getOrientation() == Surface.ROTATION_0) {
// landscape oriented devices
} else {
// portrait oriented device
}
Full code (a bit wasteful by LC, but easily demonstrates the approach)
@OverridepublicvoidonOrientationChanged(int orientation) {
// determine our orientation based on sensor responseintlastOrientation= mOrientation;
Displaydisplay= ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
if (display.getOrientation() == Surface.ROTATION_0) { // landscape oriented devicesif (orientation >= 315 || orientation < 45) {
if (mOrientation != ORIENTATION_LANDSCAPE_NORMAL) {
mOrientation = ORIENTATION_LANDSCAPE_NORMAL;
}
} elseif (orientation < 315 && orientation >= 225) {
if (mOrientation != ORIENTATION_PORTRAIT_INVERTED) {
mOrientation = ORIENTATION_PORTRAIT_INVERTED;
}
} elseif (orientation < 225 && orientation >= 135) {
if (mOrientation != ORIENTATION_LANDSCAPE_INVERTED) {
mOrientation = ORIENTATION_LANDSCAPE_INVERTED;
}
} elseif (orientation <135 && orientation > 45) {
if (mOrientation != ORIENTATION_PORTRAIT_NORMAL) {
mOrientation = ORIENTATION_PORTRAIT_NORMAL;
}
}
} else { // portrait oriented devicesif (orientation >= 315 || orientation < 45) {
if (mOrientation != ORIENTATION_PORTRAIT_NORMAL) {
mOrientation = ORIENTATION_PORTRAIT_NORMAL;
}
} elseif (orientation < 315 && orientation >= 225) {
if (mOrientation != ORIENTATION_LANDSCAPE_NORMAL) {
mOrientation = ORIENTATION_LANDSCAPE_NORMAL;
}
} elseif (orientation < 225 && orientation >= 135) {
if (mOrientation != ORIENTATION_LANDSCAPE_INVERTED) {
mOrientation = ORIENTATION_LANDSCAPE_INVERTED;
}
} elseif (orientation <135 && orientation > 45) {
if (mOrientation != ORIENTATION_PORTRAIT_NORMAL) {
mOrientation = ORIENTATION_PORTRAIT_NORMAL;
}
}
} else { // portrait oriented devicesif (orientation >= 315 || orientation < 45) {
if (mOrientation != ORIENTATION_PORTRAIT_NORMAL) {
mOrientation = ORIENTATION_PORTRAIT_NORMAL;
}
} elseif (orientation < 315 && orientation >= 225) {
if (mOrientation != ORIENTATION_LANDSCAPE_NORMAL) {
mOrientation = ORIENTATION_LANDSCAPE_NORMAL;
}
} elseif (orientation < 225 && orientation >= 135) {
if (mOrientation != ORIENTATION_PORTRAIT_INVERTED) {
mOrientation = ORIENTATION_PORTRAIT_INVERTED;
}
} elseif (orientation <135 && orientation > 45) {
if (mOrientation != ORIENTATION_LANDSCAPE_INVERTED) {
mOrientation = ORIENTATION_LANDSCAPE_INVERTED;
}
}
}
if (lastOrientation != mOrientation) {
changeRotation(mOrientation, lastOrientation);
}
}
Third ways :
private Bitmap adjustImageOrientation(Bitmap image) {
ExifInterface exif;
try {
exif = newExifInterface(picturePath);
intexifOrientation= exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
introtate=0;
switch (exifOrientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
rotate = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotate = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
rotate = 270;
break;
}
if (rotate != 0) {
intw= image.getWidth();
inth= image.getHeight();
// Setting pre rotateMatrixmtx=newMatrix();
mtx.preRotate(rotate);
// Rotating Bitmap & convert to ARGB_8888, required by tess
image = Bitmap.createBitmap(image, 0, 0, w, h, mtx, false);
}
} catch (IOException e) {
returnnull;
}
return image.copy(Bitmap.Config.ARGB_8888, true);
}
Solution 2:
I gave this answer to a similar question, but as you say it was on an HTC device. I would recommend that you add breakpoints to the rotation code and examine the variables while physically rotating the device - this may help identify whats different with the Galaxy models.
Solution 3:
Check if the "Auto-rotate Screen" option is checked in the phone Settings (Settings > Dislay or Screen - depends on the android version).
Solution 4:
Just posting a new solution that worked for me.
Basically you can get the orientation value from the Camera.CameraInfo. This will tell the degrees you need to use on setDisplayOrientation so the image is properly displayed. When using the back facing camera you can simply use setDisplayOrientation with the value retrieved, But when using the front facing camera you need to tweak it a bit as the Android system will flip the image so it appears like a mirror.
Below code worked for me and tested on 4 different devices including a Nexus6 and Galaxy.
Camera.CameraInfocameraInfo=newCamera.CameraInfo();
intcameraCount= Camera.getNumberOfCameras();
intcamIdx=0; // DO your logic to get front or back camera...or loop through all avaialable.
Camera.getCameraInfo(camIdx, cameraInfo);
try {
mCamera = Camera.open(camIdx);
// If using back camera then simply rotate what CameraInfo tells you.if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK)
mCamera.setDisplayOrientation(cameraInfo.orientation);
else// If using front camera note that image might be flipped to give users the impresion the are looking at a mirror.
mCamera.setDisplayOrientation( (360 - cameraInfo.orientation) % 360);
} catch (Exception e) {
e.printStackTrace();
}
Post a Comment for "Android Camera Setdisplayorientation(90) Fails In Different Devices"