Orientate Image Taken from camera in Android - android

I'm creating android camera app. This is an custom camera using camera API.
Whenever I take picture from camera it always save in landscap mode.
I'm using this method to set the camera orientation.
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);
}
Here is code which is responsible to store image.
PictureCallback jpegCallback = new PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
if (pictureFile == null){
Log.d(TAG, "Error creating media file, check storage permissions: ");
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d(TAG, "Error accessing file: " + e.getMessage());
}
}
};
This code save the image successfully but always in landscape mode. What I'm missing I'm new in android. I want to save image as like it is shown in preview.
Update 2 (According To Answer)
PictureCallback jpegCallback = new PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
Camera.CameraInfo info = new Camera.CameraInfo();
int rotationAngle = getCorrectCameraOrientation (MainActivity.this, info);
Toast.makeText(MainActivity.this, "Angle "+ rotationAngle, Toast.LENGTH_SHORT).show();
File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
try {
writeFile (data, pictureFile);
} catch (IOException e) {
e.printStackTrace();
}
processImage (pictureFile, rotationAngle, 1);
}
};
I'm using code in this way but this is not working still same problem image is always in landscape mode.

Try
1. First of all, add methods (writeFile, processImage and getCorrectCameraOrientation) defined below (After step 3)
2. Calculate camera orientation after capturing photo and update onPictureTaken**
#Override
public void onPictureTaken (final byte[] data, final Camera camera) {
int rotationAngle = getCorrectCameraOrientation (this, info);
3. Create file and update photo angle using rotationAngle
File file = new File (folder, fileName);
try {
file.createNewFile ();
}
catch (IOException e) {
e.printStackTrace ();
}
writeFile (data, file);
processImage (file, rotationAngle, compressRatio);
writeFile
public static void writeFile (byte[] data, File file) throws IOException {
BufferedOutputStream bos = null;
try {
FileOutputStream fos = new FileOutputStream (file);
bos = new BufferedOutputStream (fos);
bos.write (data);
}
finally {
if (bos != null) {
try {
bos.flush ();
bos.close ();
}
catch (Exception e) {
}
}
}
}
processImage
public static void processImage (File file, int rotationAngle, int compressionRatio) {
BufferedOutputStream bos = null;
try {
Bitmap bmp = BitmapFactory.decodeFile (file.getPath ());
Matrix matrix = new Matrix ();
matrix.postRotate (rotationAngle);
bmp = Bitmap.createBitmap (bmp, 0, 0, bmp.getWidth (), bmp.getHeight (), matrix, true);
FileOutputStream fos = new FileOutputStream (file);
bmp.compress (Bitmap.CompressFormat.PNG, compressionRatio, fos);
}
catch (IOException e) {
e.printStackTrace ();
}
catch (OutOfMemoryError t) {
t.printStackTrace ();
}
catch (Throwable t) {
t.printStackTrace ();
}
finally {
if (bos != null) {
try {
bos.flush ();
bos.close ();
}
catch (Exception e) {
}
}
}
}
getCorrectCameraOrientation
public static int getCorrectCameraOrientation (Activity activity, Camera.CameraInfo info) {
int rotation = activity.getWindowManager ().getDefaultDisplay ().getRotation ();
int degrees = 0;
if (hasValidRotation (rotation)) {
degrees = rotation * 90;
}
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;
}

Related

CropImageView Transaction too large Exception

I am having trouble with a transaction too large exception related to the cropImageView. Anytime I use the cropImageView to crop an image and then use an intent to change the activity, it gives me a Transaction too large exception.
I went on and saw that it may be cause I am passing too much data from one activity to another but even when I took the part of my code that passes a byte array in the intent it still crashes with the transaction too large exception.
Here is my code:
public class TestActivity extends AppCompatActivity {
private CropImageView cropImageView;
private Button cropImage;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
cropImage = (Button) findViewById(R.id.cropImage);
cropImageView = (CropImageView) findViewById(R.id.cropImageView);
Intent intent = getIntent();
byte[] bite = intent.getExtras().getByteArray("imageForCropping");
Bitmap bitmap = getPhoto(bite);
cropImageView.setImageBitmap(bitmap);
cropImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Bitmap bit = cropImageView.getCroppedImage();
byte[] byteArray = getBytes(bit);
Intent intent = new Intent(TestActivity.this, HomeScreenActivity.class);
intent.putExtra("croppedImage", byteArray);
TestActivity.this.startActivity(intent);
}
});
}
public static Bitmap getPhoto(byte[] image) {
return BitmapFactory.decodeByteArray(image, 0, image.length );
}
public static byte[] getBytes(Bitmap image) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.PNG, 100, stream);
return stream.toByteArray();
}
}
I have tried to avoid using this intent to pass the byte array by using a sqlite database but it still crashes with a transaction too large exception. So this led me to believe that CropImageView is causing the problem.
Please let me know if you know what the problem could be.
Thanks in advance!
It's a bug in the cropImageView, it attempts to save the image as its own view state when onSaveInstanceState() is called.
The solution is to save the image out into a file, and call setImageBitmap(null) on the crop image view before calling super.onSaveInstanceState(), then restore the image bitmap when needed from the file.
EDIT: Okay, I'll share my code on this, but it's really really hacky. I was happy that it worked. Also, it's from a camera, so I took the photo and got the bitmap as a byte array.
Please advise caution.
#Override
public void onResume() {
if(cameraPresenter != null) {
cameraPresenter.onResume();
}
if(takenBitmap != null && !takenBitmap.isRecycled()) {
takenPhotoDisplay.setImageBitmap(takenBitmap);
}
}
#Override
public void onViewDestroyed(boolean removedByFlow) {
takenPhotoDisplay.setImageBitmap(null);
}
#Override // called before `Activity super.onSaveInstanceState()`
public void preSaveViewState(Bundle bundle) {
takenPhotoDisplay.setImageBitmap(null);
}
private byte[] takenPhoto;
private Bitmap takenBitmap;
private void restoreBitmap() {
try {
takenPhoto = readByteArrayFromFile("TEMP");
} catch(FileNotFoundException e) {
Log.e(TAG, "No bitmap found to restore");
} catch(IOException e) {
Log.e(TAG, "Could not read bitmap");
}
}
private byte[] readByteArrayFromFile(String fileName)
throws IOException {
Context context = CustomApplication.get();
byte[] result = null;
FileInputStream fileInputStream = null;
try {
fileInputStream = context.openFileInput(fileName);
result = IOUtils.toByteArray(fileInputStream);
} catch(FileNotFoundException e) {
Log.e(TAG, "The file was not found [" + fileName + "]", e);
throw e;
} catch(IOException e) {
Log.e(TAG, "Unable to read data from stream [" + fileName + "]", e);
throw e;
} finally {
if(fileInputStream != null) {
try {
fileInputStream.close();
} catch(IOException e) {
Log.e(TAG, "Could not close.");
}
}
}
return result;
}
private void preserveBitmap() {
if(takenPhoto != null) {
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = CustomApplication.get().openFileOutput("TEMP", Context.MODE_PRIVATE);
fileOutputStream.write(takenPhoto);
} catch(FileNotFoundException e) {
Log.e(TAG, "Could not open temp");
} catch(IOException e) {
Log.e(TAG, "Could not write temp");
} finally {
if(fileOutputStream != null) {
try {
fileOutputStream.close();
} catch(IOException e) {
Log.e(TAG, "Nobody cares!");
}
}
}
}
}
private void destroyCurrentBitmap() {
if(takenBitmap != null) {
takenPhotoDisplay.setImageBitmap(null);
takenBitmap.recycle();
takenBitmap = null;
takenPhoto = null;
Runtime.getRuntime().gc();
}
}
private void handleTakenPhoto(byte[] data) {
CameraView.this.takenPhoto = data;
if(takenPhoto != null) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
Bitmap bm = BitmapFactory.decodeByteArray(takenPhoto, 0, takenPhoto.length, options);
Log.d(TAG, "The Bitmap has width [" + bm.getWidth() + "] and height [" + bm.getHeight() + "]");
// Setting post rotate to 90
Matrix mtx = new Matrix();
Log.i(TAG, "CURRENT ROTATION ANGLE: [" + getRotationAngle() + "]");
// Rotating Bitmap
mtx.postRotate(getRotationAngle());
// Flipping bitmap
android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(getActiveCameraId(), info);
if(info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
mtx.postScale(-1, 1, bm.getWidth() / 2, bm.getHeight() / 2);
}
Runtime.getRuntime().gc();
Bitmap newBitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), mtx, true);
if(bm != newBitmap) {
bm.recycle();
bm = newBitmap; //yes, this is on purpose!
Runtime.getRuntime().gc();
} else {
Log.i(TAG, "The created bitmap is the same as the previous one.");
}
bm = newBitmap; //yes, this is on purpose!
takenBitmap = bm;
if(takenBitmap != null && !takenBitmap.isRecycled()) {
takenPhotoDisplay.setImageBitmap(takenBitmap);
} else {
Log.w(TAG, "The bitmap in [takenBitmap] is recycled!");
takenPhotoDisplay.setImageBitmap(null);
}
} else {
Log.w(TAG, "The taken photo is NULL.");
}
}
//IMAGE ROTATION FIX
public int getRotationAngle(int cameraId) {
android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
Activity activity = ActivityUtils.getActivity(getContext());
WindowManager windowManager = activity.getWindowManager();
Display defaultDisplay = windowManager.getDefaultDisplay();
int rotation = defaultDisplay.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;
//}
if(info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
result = (info.orientation - degrees + 540) % 360;
} else {
result = (info.orientation - degrees + 360) % 360;
}
} else {
result = (info.orientation - degrees + 360) % 360;
}
return result;
}
Do not pass bytes of image in intent or anywhere. Save it on disk, pass only the URI, and read image from disk

Camera is skewed and rotated

Its the first time i have used surface view and surface holder with a very rough knowledge of both, the live image preview in the surfaceview is skewed and rotated, on searching i found out i need to set CameraParameter but i could understand how it works and also is there any guide to understanding the Camera2 api
public class CamActivity extends AppCompatActivity implements SurfaceHolder.Callback{
Camera mCamera;
SurfaceView surfaceView;
private SurfaceHolder mHolder;
FloatingActionButton cam;
private static final int pRequestCode = 5002;
private static final String[] mPermissions = {Manifest.permission.CAMERA, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE};
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.cam_layout);
checkCameraHardware();
checkPermissions();
View decorView = getWindow().getDecorView();
int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN;
decorView.setSystemUiVisibility(uiOptions);
surfaceView = (SurfaceView) findViewById(R.id.camera_preview);
mHolder = surfaceView.getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
cam = (FloatingActionButton) findViewById(R.id.fabCamera);
cam.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mCamera.takePicture(null, null, mPicture);
}
}
);
}
private boolean checkCameraHardware() {
if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
// this device has a camera
return true;
} else {
// no camera on this device
return false;
}
}
private void checkPermissions() {
if (ContextCompat.checkSelfPermission(this, mPermissions[0]) != PackageManager.PERMISSION_GRANTED
||ContextCompat.checkSelfPermission(this, mPermissions[1]) != PackageManager.PERMISSION_GRANTED
||ContextCompat.checkSelfPermission(this, mPermissions[2]) != PackageManager.PERMISSION_GRANTED
||ContextCompat.checkSelfPermission(this, mPermissions[3]) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, mPermissions, pRequestCode);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode) {
case pRequestCode: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this,"Camera Allowed",Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this,"Camera Denied",Toast.LENGTH_SHORT).show();
}
if (grantResults.length > 0 && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this,"Location Allowed",Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this,"Location Denied",Toast.LENGTH_SHORT).show();
}
if (grantResults.length > 0 && grantResults[2] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this,"Microphone Allowed",Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this,"Microphone Denied",Toast.LENGTH_SHORT).show();
}
if (grantResults.length > 0 && grantResults[3] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this,"Storage Allowed",Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this,"Storage Denied",Toast.LENGTH_SHORT).show();
}
return;
}
}
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
try {
mCamera = Camera.open();
}
catch (Exception e){
}
Camera.Parameters parameters = mCamera.getParameters();
parameters.set("orientation", "portrait");
mCamera.setParameters(parameters);
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if (mHolder.getSurface() == null){
// preview surface does not exist
return;
}
try {
mCamera.stopPreview();
} catch (Exception e){
}
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
private Camera.PictureCallback mPicture = new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
if (pictureFile == null){
Log.d("", "Error creating media file, check storage permissions: " );
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
Log.d("", "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d("", "Error accessing file: " + e.getMessage());
}
}
};
private static File getOutputMediaFile(int type){
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES), "MyCameraApp");
if (! mediaStorageDir.exists()){
if (! mediaStorageDir.mkdirs()){
Log.d("MyCameraApp", "failed to create directory");
return null;
}
}
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE){
mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_"+ timeStamp + ".jpg");
} else if(type == MEDIA_TYPE_VIDEO) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator + "VID_"+ timeStamp + ".mp4");
} else {
return null;
}
return mediaFile;
}
}
For Camera2 API you can check Android code sample from Android Studio or GitHub.
You can solve camera preview rotation and aspect ratio in surfaceCreated() like this. Note that you'll have to properly deal with the exceptions:
#Override
public void surfaceCreated(SurfaceHolder holder) {
// You need to open the camera in a
// different manner so you can obtain some info from it
int numberOfCameras = Camera.getNumberOfCameras();
Camera.CameraInfo info = new Camera.CameraInfo();
mCamera = null;
for (int i = 0; i < numberOfCameras; i++) {
Camera.getCameraInfo(i, info);
// Open a back camera
if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
try {
mCamera = Camera.open(i);
break;
} catch (RuntimeException e) {
// Could not open camera
}
}
}
if (mCamera == null) {
// No camera found
}
Camera.Parameters parameters = mCamera.getParameters();
// Rotate display
// Code from here:
// https://developer.android.com/reference/android/hardware/Camera.html#setDisplayOrientation(int)
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;
}
mCamera.setDisplayOrientation(result);
Camera.Size size = parameters.getPreviewSize();
// You'll probably want to set the preview
// width and height to match the preview size
// aspect ratio that you can obtain by:
// (double) size.width / (double) size.height
//
// Note that if the int result above modulo 180
// equals 90, you'll have to exchange width for height
// and vice versa.
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}

Android camera's image saved in horizontal mode in my app

I made a simple camera application with android. But there is one problem that I cannot solve. My camera app's surfaceView is in portrait mode , however, when I take the image and save the image in the folder. It's not saved in a portrait mode. Since, I'm new to android development I would need some help. I've put some code below.
PictureCallback jpegCallback = new PictureCallback() {
#SuppressWarnings("deprecation")
public void onPictureTaken(byte[] data, Camera camera) {
FileOutputStream outStream = null;
Calendar c = Calendar.getInstance();
File videoDirectory = new File(path);
if (!videoDirectory.exists()) {
videoDirectory.mkdirs();
}
try {
// Write to SD Card
outStream = new FileOutputStream(path + c.getTime().getSeconds() + ".jpg");
outStream.write(data);
outStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
Bitmap realImage;
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 5;
options.inPurgeable=true; //Tell to gc that whether it needs free memory, the Bitmap can be cleared
options.inInputShareable=true; //Which kind of reference will be used to recover the Bitmap data after being clear, when it will be used in the future
realImage = BitmapFactory.decodeByteArray(data,0,data.length,options);
ExifInterface exif = null;
try {
exif = new ExifInterface(path + c.getTime().getSeconds()
+ ".jpg");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
Log.d("EXIF value",
exif.getAttribute(ExifInterface.TAG_ORIENTATION));
if (exif.getAttribute(ExifInterface.TAG_ORIENTATION)
.equalsIgnoreCase("1")) {
realImage = rotate(realImage, 90);
} else if (exif.getAttribute(ExifInterface.TAG_ORIENTATION)
.equalsIgnoreCase("8")) {
realImage = rotate(realImage, 90);
} else if (exif.getAttribute(ExifInterface.TAG_ORIENTATION)
.equalsIgnoreCase("3")) {
realImage = rotate(realImage, 90);
} else if (exif.getAttribute(ExifInterface.TAG_ORIENTATION)
.equalsIgnoreCase("0")) {
realImage = rotate(realImage, 90);
}
} catch (Exception e) {
}
image.setImageBitmap(realImage);
fotoButton.setClickable(true);
camera.startPreview();
progressLayout.setVisibility(View.GONE);
exitButton.setClickable(true);
}
};
public static Bitmap rotate(Bitmap source, float angle) {
Matrix matrix = new Matrix();
matrix.postRotate(angle);
return Bitmap.createBitmap(source, 0, 0, source.getWidth(),
source.getHeight(), matrix, false);
}
try below methods some times some device have orientantion roated to 90 or 180 or 270 here is the methods try this to get image in normal mode if its gets rotated:
public static Bitmap RotateImage(String imagePath, boolean rotateImage) {
Matrix imageMatrix = new Matrix();
if (rotateImage) {
int rotationNeeded = getImageRotationDegrees(imagePath);
if (rotationNeeded != 0) {
imageMatrix.postRotate(rotationNeeded);
}
}
public static int getImageRotationDegrees(String imagePath) {
int currentRotation = getImageOrientation(imagePath);
switch (currentRotation) {
case ExifInterface.ORIENTATION_ROTATE_90:
return 90;
case ExifInterface.ORIENTATION_ROTATE_180:
return 180;
case ExifInterface.ORIENTATION_ROTATE_270:
return 270;
}
return 0;
}
public static int getImageOrientation(String imagePath) {
ExifInterface exifInterface;
try {
exifInterface = new ExifInterface(imagePath);
} catch (IOException e) {
return ExifInterface.ORIENTATION_UNDEFINED;
}
return exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_UNDEFINED);
}

Android image captured orientation is wrong ( custom camera)

i've been struggling with the problem below, i found some tutorials and made a custom camera with a SurfaceView as a preview holder.
I'm mainly concerned for the front Camera.
Now when i take an image while the preview works fine the image is being saved with a wrong rotation in my SD card.
Below are the main two functions. Setup of the camera and the take picture.
*private void setUpCamera(Camera c) {
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(cameraId, info);
rotation = getWindowManager().getDefaultDisplay().getRotation();
int degree = 0;
switch (rotation) {
case Surface.ROTATION_0:
degree = 0;
break;
case Surface.ROTATION_90:
degree = 90;
break;
case Surface.ROTATION_180:
degree = 180;
break;
case Surface.ROTATION_270:
degree = 270;
break;
default:
break;
}
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
// frontFacing
rotation = (info.orientation + degree) % 360;
rotation = (360 - rotation) % 360;
} else {
// Back-facing
rotation = (info.orientation - degree + 360) % 360;
}
c.setDisplayOrientation(rotation);
Parameters params = c.getParameters();
List<String> focusModes = params.getSupportedFlashModes();
if (focusModes != null) {
if (focusModes
.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
params.setFlashMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
}
}
params.setRotation(rotation);
c.setParameters(params);
}*
private void takeImage() {
camera.takePicture(null, null, new PictureCallback() {
private File imageFile;
#Override
public void onPictureTaken(byte[] data, Camera camera) {
try {
// convert byte array into bitmap
Bitmap loadedImage = null;
loadedImage = BitmapFactory.decodeByteArray(data, 0,data.length);
// rotate Image
Matrix rotateMatrix = new Matrix();
rotateMatrix.postRotate(rotation);
loadedImage = Bitmap.createBitmap(loadedImage, 0, 0,loadedImage.getWidth(), loadedImage.getHeight(),rotateMatrix, false);
//create folder if it doesnt exists
String state = Environment.getExternalStorageState();
File folder = null;
if (state.contains(Environment.MEDIA_MOUNTED)) {
folder = new File(Environment
.getExternalStorageDirectory() + "/Squote");
} else {
folder = new File(Environment
.getExternalStorageDirectory() + "/Squote");
}
boolean success = true;
if (!folder.exists()) {
success = folder.mkdirs();
}
if (success) {
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss",
Locale.getDefault()).format(new Date());
imageFile = new File(folder.getAbsolutePath()
+ File.separator
+ "IMG_"
+ timeStamp
+ ".jpg");
imageFile.createNewFile();
} else {
Toast.makeText(getBaseContext(), "Image Not saved",Toast.LENGTH_SHORT).show();
return;
}
ByteArrayOutputStream ostream = new ByteArrayOutputStream();
// save image into gallery
loadedImage.compress(CompressFormat.JPEG, 100, ostream);
FileOutputStream fout = new FileOutputStream(imageFile);
fout.write(ostream.toByteArray());
fout.close();
ContentValues values = new ContentValues();
values.put(Images.Media.DATE_TAKEN,System.currentTimeMillis());
values.put(Images.Media.MIME_TYPE, "image/jpeg");
values.put(MediaStore.MediaColumns.DATA, imageFile.getAbsolutePath());
//release camera and return image
releaseCamera();
Intent intentMessage = new Intent();
intentMessage.putExtra("imageUri", imageFile.getAbsolutePath());
setResult(RESULT_OK, intentMessage);
finish();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
On the rotate image part of the code if i put 270 it shows up correct BUT i'm having another issue there. The image is not the same as the preview but it's mirrored. I think also that a fixed 270 value is not a solution as it messes up the back camera or the portrait pictures.
Any help would be much appreciated.
Thank you
It's not an issue, it's how the front-facing camera works. Even if you take a picture with your phone's camera app it will be flipped when saved. You can implement a method to flip the image vertically if that is the result you are trying to get.

Exif orientation tag returns 0

I am developing a custom camera application and I am facing the following problem. When I try to retrieve an orientation using ExifInterface, it always returns 0 (ORIENTATION_UNDEFINED). This prevents me from rotating the image to the proper state so it can be displayed correctly.
I use a sample code for setting the camera rotation (method containing this code is called before startPreview()):
android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(0, info);
screenOrientation = getWindowManager().getDefaultDisplay().getOrientation();
Log.d(TAG, "Screen orientation: " + screenOrientation);
screenOrientation = (screenOrientation + 45) / 90 * 90;
int rotation = 0;
if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
rotation = (info.orientation - screenOrientation + 360) % 360;
}
else{
//back-facing camera
rotation = (info.orientation + screenOrientation) % 360;
Log.d("Test", "Calculated Rotation" + rotation);
}
params.setRotation(rotation);
camera.setParameters(params);
The way I save the taken picture:
#Override
public void onPictureTaken(byte[] data, Camera camera) {
File photoFileDir = getFileDir();
if (!photoFileDir.exists() && !photoFileDir.mkdirs()){
Toast.makeText(context, "Cannot create directory for the taken picture", Toast.LENGTH_LONG).show();
return;
}
String pictureName = "photo_" + getPictureDate() + ".jpg";
String picturePath = photoFileDir.getPath() + File.separator + pictureName;
File pictureFile = new File(picturePath);
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
try {
fos.write(data);
fos.close();
sendPictureSavedBroadcast(context, picturePath);
Toast.makeText(context, "Picture saved!", Toast.LENGTH_LONG).show();
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(context, "Picture could not be saved", Toast.LENGTH_LONG).show();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
The way I try to retrieve the picture orientation:
public static int getRotation(String absolutePath){
try{
ExifInterface exif = new ExifInterface(absolutePath);
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, -1);
Log.d(TAG, "Toolkit, orientation: " + orientation);
switch(orientation){
case ExifInterface.ORIENTATION_NORMAL:
Log.d(TAG, "Image is properly rotated");
return 0;
case ExifInterface.ORIENTATION_ROTATE_90:
return 90;
case ExifInterface.ORIENTATION_ROTATE_180:
return 180;
case ExifInterface.ORIENTATION_ROTATE_270:
return 270;
case ExifInterface.ORIENTATION_UNDEFINED:
Log.d(TAG, "Error getting orientation");
return -1;
default:
Log.d(TAG, "Error getting orientation");
return -1;
}
}
catch(Exception e){
e.printStackTrace();
}
return -1;
}
I went through all the similar topics on stackoverflow, but did not find the solution. I would appreciate any suggestions!

Categories

Resources