I want to add image capturing in my Android app where user can captures images, I'm using the following code:
public void open_camera() {
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
try {
// place where to store camera taken picture
photo = this.createTemporaryFile("picture", ".jpg");
photo.delete();
} catch(Exception e) {
Toast.makeText(this, "Please check SD card! Image shot is impossible!", 10000);
}
mImageUri = Uri.fromFile(photo);
intent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri);
//start camera intent
startActivityForResult(intent,SELECT_PICTURE_CAMERA );
//Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
//startActivityForResult(cameraIntent, SELECT_PICTURE_CAMERA);
}
private File createTemporaryFile(String part, String ext) throws Exception {
File tempDir= Environment.getExternalStorageDirectory();
tempDir=new File(tempDir.getAbsolutePath()+"/.temp/");
if(!tempDir.exists()) {
tempDir.mkdir();
}
return File.createTempFile(part, ext, tempDir);
}
When I retrieve
case SELECT_PICTURE_CAMERA:
if(resultCode == RESULT_OK) {
// Toast.makeText(this,"Camera" + imageReturnedIntent.getStringExtra(ZBarConstants.SCAN_RESULT), Toast.LENGTH_LONG).show();
//this.yourSelectedImage = (Bitmap) imageReturnedIntent.getExtras().get("data");
/*
ImageButton imgbtn = (ImageButton) findViewById(R.id.imageButton_Photo);
BitmapDrawable background = new BitmapDrawable(this.yourSelectedImage);
imgbtn.setBackgroundDrawable(background);
*/
try {
File f=new File(mImageUri.getPath());
ExifInterface exif = new ExifInterface(f.getPath());
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
int angle = 0;
if (orientation == ExifInterface.ORIENTATION_ROTATE_90) {
angle = 90;
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) {
angle = 180;
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) {
angle = 270;
}
Matrix mat = new Matrix();
mat.postRotate(90);
Bitmap bmp = BitmapFactory.decodeStream(new FileInputStream(f), null, null);
this.yourSelectedImage = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), mat, true);
} catch (IOException e) {
Log.w("TAG", "-- Error in setting image");
} catch(OutOfMemoryError oom) {
Log.w("TAG", "-- OOM Error in setting image");
}
But unfortunately after doing all this, still image is not of full size and it's always landscape.
You have a small mistake in code, after you get the angle the image should rotate you need to use this value in postRotate.
Please replace the line:
mat.postRotate(90);
with:
mat.postRotate(angle);
Hope I helped you :-)
Regards,
Woody.
Related
I have a code, where you can take a picture, and then save it like 1.jpg,2.jpg,3.jpg. The problem is that I have no idea how to display the taken image in my second activity.
Button capture = (Button) findViewById(R.id.btnCapture);
capture.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Here, the counter will be incremented each time, and the
// picture taken by camera will be stored as 1.jpg,2.jpg
// and likewise.
count++;
String file = dir+count+".jpg";
File newfile = new File(file);
try {
newfile.createNewFile();
}
catch (IOException e)
{
}
Uri outputFileUri = Uri.fromFile(newfile);
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
startActivityForResult(cameraIntent, TAKE_PHOTO_CODE);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == TAKE_PHOTO_CODE && resultCode == RESULT_OK) {
Log.d("CameraDemo", "Pic saved");
}
}
}
If I try to pass my image as parcable, the quality is pretty bad, that's what I don't want. Anybody can help me with this, or show a good guide? The most important is that I don't want to display it in my first activity, I want to display it in my second activity, calling the path of the 1.jpg. Thanks!
The way is to write the picture taken to a file and get the path to said file and passing the path to the next activity and intializing a bitmap using said path to file and setting the image view...ill post a code soon
mean while look into here while i post a snippet
EDIT: SNIPPET
this code sets up camera to take a picture and save to a file.
private void onCameraSelected() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
fileUri = getOutputMediaFileUri();
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
startActivityForResult(intent, PICTURE_CAMERA);
}
private Uri getOutputMediaFileUri() {
return Uri.fromFile(getOutputMediaFile());
}
private File getOutputMediaFile() {
// External sdcard location
File mediaStorageDir = new File(
Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
IMAGE_DIRECTORY_NAME);
// Create the storage directory if it does not exist
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d(IMAGE_DIRECTORY_NAME, "Oops! Failed create "
+ IMAGE_DIRECTORY_NAME + " directory");
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss",
Locale.getDefault()).format(new Date());
File mediaFile;
mediaFile = new File(mediaStorageDir.getPath() + File.separator
+ "IMG_" + timeStamp + ".jpg");
return mediaFile;
}
on the onActivityResult detect resultcode/request code for camera and consume it like so
private void loadImageFromCamera(Intent data) {
try {
BitmapFactory.Options options = new BitmapFactory.Options();
// downsizing image as it throws OutOfMemory Exception for larger images
// options.inSampleSize = 8;
Bitmap bitmap = BitmapFactory.decodeFile(fileUri.getPath(), options);
setLoadedImage(bitmap);// set bitmap to imageview here.
} catch (NullPointerException e) {
e.printStackTrace();
} catch (IOException e) {
Logger.logError("File not found :" + fileUri.getPath());
e.printStackTrace();
}
}
Basically youre playing with the variable String filePath = fileUri.getPath(); // just declare Uri fileUri in activity level or something.
You will need to pass the camera intent a location to save the image. You then have to retrieve the image from the phones storage in order to display it in an image view.
set a member variable to keep track of the image:
private Uri mImageUir;
Then to request a camera intent:
File photo = null;
try {
// place where to store camera taken picture
photo = createTemporaryFile("picture", ".jpg");
photo.delete();
} catch (Exception e) {
e.printStackTrace();
}
mImageUir = Uri.fromFile(photo);
intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUir);
activity.startActivityForResult(intent, TAKE_PHOTO);
...
private File createTemporaryFile(String part, String ext) throws Exception
{
File tempDir= Environment.getExternalStorageDirectory();
tempDir=new File(tempDir.getAbsolutePath()+"/.temp/");
if(!tempDir.exists())
{
tempDir.mkdir();
}
return File.createTempFile(part, ext, tempDir);
}
Then in your OnActivityResult
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if(resultCode == Activity.RESULT_OK) {
//firstly find correct orientation of photo
ExifInterface exif = null;
Integer photoOrientation = null;
try {
exif = new ExifInterface(mImageUir.getPath());
photoOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
} catch (IOException e) {
e.printStackTrace();
}
Bitmap photo;
ContentResolver resolver = getContext().getContentResolver();
try {
//get the image file
photo = MediaStore.Images.Media.getBitmap(resolver, mImageUir);
//You should scale it down here if you dont need in full size
//rotate to correct orientation
if(photoOrientation != null) {
photo = rotateBitmap(photo, photoOrientation);
}
mYourImageView.setImageBitmap(photo);
//delete temporary image file (if you need to)
}
catch (Exception e){
e.printStackTrace();
}
}
}
and here is my method to rotate the image:
public static Bitmap rotateBitmap(Bitmap bitmap, int orientation) {
Matrix matrix = new Matrix();
switch (orientation) {
case ExifInterface.ORIENTATION_NORMAL:
return bitmap;
case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
matrix.setScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
matrix.setRotate(180);
break;
case ExifInterface.ORIENTATION_FLIP_VERTICAL:
matrix.setRotate(180);
matrix.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_TRANSPOSE:
matrix.setRotate(90);
matrix.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_90:
matrix.setRotate(90);
break;
case ExifInterface.ORIENTATION_TRANSVERSE:
matrix.setRotate(-90);
matrix.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
matrix.setRotate(-90);
break;
default:
return bitmap;
}
try {
Bitmap bmRotated = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
bitmap.recycle();
return bmRotated;
}
catch (OutOfMemoryError e) {
e.printStackTrace();
return null;
}
}
I have an activity to open camera intent and grab the photo in the onActivityResult method.
Three devices worked well without errors but only in one device I get null error on the file variable.
"Attempt to invoke virtual method java.lang.String java.io.File.getPath() on a null object reference"
This is the way how I implemented it.
A) Step one: Open camera
Upon clicking on a button I run the following code. This code will:
Create a new file
Open camera intent
//create file
imgName = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()) + ".jpg";
//global variable
file = new File(Environment.getExternalStorageDirectory(), imgName);
if(file != null){
//save image here
Uri relativePath = Uri.fromFile(file);
//Open camera
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, relativePath);
startActivityForResult(intent, Constant.CAMERA_PIC_REQUEST);
}
B) Step two: Take a picture and click save button
C) Step three: Grab the picture in onActivityResult() method
Check the constant = Constant.CAMERA_PIC_REQUEST.
Get the EXIF data from the photo and find out the required angle to rotate the photo.
Set the width, height and angle. Create the .jpg photo
Save the created image name and path into imageArray
Set the grid view with imageArray
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
switch (requestCode) {
case Constant.CAMERA_PIC_REQUEST:
try {
//Get EXIF data and rotate photo (1. file.getPath() has been used)
ExifInterface exif = new ExifInterface(file.getPath());
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
int angle = 0;// Landscape
//rotate photo
if (orientation == ExifInterface.ORIENTATION_ROTATE_90) {
angle = 90;
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) {
angle = 180;
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) {
angle = 270;
}
Matrix matrix = new Matrix();
matrix.postRotate(angle);
try {
//Create the rotated .jpg file (2. file.getPath() has been used)
Bitmap correctBmp = Func.decodeSampleBitmapFromFile(file.getPath(), Constant.PHOTO_WIDTH, Constant.PHOTO_HEIGHT);
correctBmp = Bitmap.createBitmap(correctBmp, 0, 0, correctBmp.getWidth(), correctBmp.getHeight(), matrix, true);
FileOutputStream fOut;
fOut = new FileOutputStream(file);
correctBmp.compress(Bitmap.CompressFormat.JPEG, 80, fOut);
fOut.flush();
fOut.close();
//image saved successfully - add photo name into reference array. Later I will use this
//(3. file.getPath() has been used)
Image img = new Image();
img.setImageName(imgName);
img.setAbsolutePath(file.getAbsolutePath());
img.setRelativePath(Uri.fromFile(file));
imageArray.add(img);//save in array
} catch (FileNotFoundException e) {
Log.e("Error", e.getMessage());
} catch (IOException e) {
Log.e("Error", e.getMessage());
}
} catch (Exception e) {
//This exception is triggering.
Log.e("Error 15", e.getMessage());
}
//set this photo in a grid view for user to see
setGridView(imageArray);
break;
case Constant.POPUPFRAG:
//something else
break;
default:
//deafult
break;
}
}
}
Error 15 (third exception) is triggering only in one phone. I'm not sure why is that. It shows the null pointer exception that I posted above.
Three devices that could run above code is having at least android v4.0 or above.
The phone that gives me null exception is Samsung Galaxy Note 3 Android v5.0. (Although the code is failing, I could find the photo in the phone gallery)
Can you please suggest me what could go wrong here? Am I missing something?
Anyway to improve this code?
Thanks!
Instead of directly using file.getPath() you can get use like this.
Create Global varibale of Uri then use it in all activity.
private Uri imageToUploadUri;
file = new File(Environment.getExternalStorageDirectory(), imgName);
if(file != null){
//save image here
imageToUploadUri = Uri.fromFile(file);
//Open camera
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageToUploadUri);
startActivityForResult(intent, Constant.CAMERA_PIC_REQUEST);
}
then in your onActivityResult() use like this:
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
switch (requestCode) {
case Constant.CAMERA_PIC_REQUEST:
try {
ExifInterface exif = new ExifInterface(imageToUploadUri.getPath());
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
int angle = 0;// Landscape
//rotate photo
if (orientation == ExifInterface.ORIENTATION_ROTATE_90) {
angle = 90;
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) {
angle = 180;
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) {
angle = 270;
}
Matrix matrix = new Matrix();
matrix.postRotate(angle);
try {
//Create the rotated .jpg file (2. file.getPath() has been used)
Bitmap correctBmp = Func.decodeSampleBitmapFromFile(imageToUploadUri.getPath(), Constant.PHOTO_WIDTH, Constant.PHOTO_HEIGHT);
correctBmp = Bitmap.createBitmap(correctBmp, 0, 0, correctBmp.getWidth(), correctBmp.getHeight(), matrix, true);
FileOutputStream fOut;
fOut = new FileOutputStream(file);
correctBmp.compress(Bitmap.CompressFormat.JPEG, 80, fOut);
fOut.flush();
fOut.close();
//image saved successfully - add photo name into reference array. Later I will use this
//(3. file.getPath() has been used)
Image img = new Image();
img.setImageName(imgName);
img.setAbsolutePath(file.getAbsolutePath());
img.setRelativePath(imageToUploadUri);
imageArray.add(img);//save in array
} catch (FileNotFoundException e) {
Log.e("Error", e.getMessage());
} catch (IOException e) {
Log.e("Error", e.getMessage());
}
} catch (Exception e) {
//This exception is triggering.
Log.e("Error 15", e.getMessage());
}
//set this photo in a grid view for user to see
setGridView(imageArray);
break;
case Constant.POPUPFRAG:
//something else
break;
default:
//deafult
break;
}
}
}
I hope it helps you!
I have been stuck in camera for 6 days but not getting any proper solution. When I am capturing image through camera intent, image is being rotated. I tried to fix the orientation but sometimes it's not giving bitmap value in onActivityResult(). It shows a black screen when I try to set image in ImageView. Here is my code Please help me -
//call intent to capture image
captureBtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
try {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getActivity().getPackageManager()) != null)
{
startActivityForResult(takePictureIntent,AlletConstants.CAPTURE_RECEIPT_IMAGE);
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case AlletConstants.CAPTURE_RECEIPT_IMAGE:
if(data != null)
{
Uri qrcodeImageUri = data.getData();
bitmapReceiptImage = handleQrBarCodeImage(qrcodeImageUri);
mImageCaptureUri = AlletCommonUtility.bitmapToUri(getActivity(), bitmapReceiptImage);
doCrop();
AlletCommonUtility.showToast(getActivity(),"Uri = "+mImageCaptureUri);
}
break;
case AlletConstants.CROP_RECEIPT_FROM_CAMERA:
if(data != null)
{
Bundle qrcodeextras = data.getExtras();
if (qrcodeextras != null) {
Bitmap cropBitmap = qrcodeextras.getParcelable("data");
receiptImageView.setImageBitmap(cropBitmap);
bitmapReceiptImage = cropBitmap;
}
File qrcodeFile = new File(mImageCaptureUri.getPath());
if (qrcodeFile.exists())
qrcodeFile.delete();
}
break;
default:
break;
}
}
// use to get bitmap from uri
private Bitmap handleReceiptImage(Uri selectedImageUri)
{
String[] filePathColumn = {MediaStore.Images.Media.DATA };
Cursor cursor = getActivity().getContentResolver().query(selectedImageUri, filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
picturePath = cursor.getString(columnIndex);
cursor.close();
Bitmap bitmap = setCameraImageRotation(picturePath);
return bitmap;
}
private Bitmap setCameraImageRotation(String picturePath)
{
Bitmap bitmapQrBarImage = null;
try {
File f = new File(picturePath);
ExifInterface exif = new ExifInterface(f.getPath());
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
AlletCommonUtility.showToast(getActivity(), "Orienattion = "+orientation);
Matrix mat = new Matrix();
mat.postRotate(getImageOrientation(orientation));
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize= 4;
Bitmap bmp = BitmapFactory.decodeStream(new FileInputStream(f), null, options);
bitmapQrBarImage = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), mat, true);
if (bitmapQrBarImage != null) {
AlletCommonUtility.showToast(getActivity(), "CAMERA_PIC_SELECTION = "+bitmapQrBarImage);
}
}
catch (IOException e) {
Log.w("TAG", "-- Error in setting image");
}
catch(OutOfMemoryError oom) {
Log.w("TAG", "-- OOM Error in setting image");
}
return bitmapQrBarImage;
}
// Use to crop image
private void doCrop() {
final ArrayList<CropOption> cropOptions = new ArrayList<CropOption>();
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setType("image/*");
List<ResolveInfo> list = getActivity().getPackageManager().queryIntentActivities( intent, 0 );
int size = list.size();
if (size == 0) {
AlletCommonUtility.showToast(getActivity(), AlletMessage.NOT_CROP_IMAGE);
return;
} else {
intent.setData(mImageCaptureUri);
intent.putExtra("outputX", 200);
intent.putExtra("outputY", 200);
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
intent.putExtra("scale", true);
intent.putExtra("return-data", true);
if (size == 1) {
Intent i = new Intent(intent);
ResolveInfo res = list.get(0);
i.setComponent( new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
startActivityForResult(i, AlletConstants.CROP_RECEIPT_FROM_CAMERA);
} else {
for (ResolveInfo res : list) {
final CropOption co = new CropOption();
co.title = getActivity().getPackageManager().getApplicationLabel(res.activityInfo.applicationInfo);
co.icon = getActivity().getPackageManager().getApplicationIcon(res.activityInfo.applicationInfo);
co.appIntent= new Intent(intent);
co.appIntent.setComponent( new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
cropOptions.add(co);
}
CropOptionAdapter adapter = new CropOptionAdapter(getActivity(), cropOptions);
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("Choose Crop App");
builder.setAdapter( adapter, new DialogInterface.OnClickListener() {
public void onClick( DialogInterface dialog, int item ) {
startActivityForResult( cropOptions.get(item).appIntent, AlletConstants.CROP_RECEIPT_FROM_CAMERA);
}
});
builder.setOnCancelListener( new DialogInterface.OnCancelListener() {
#Override
public void onCancel( DialogInterface dialog ) {
if (mImageCaptureUri != null ) {
getActivity().getContentResolver().delete(mImageCaptureUri, null, null );
mImageCaptureUri = null;
}
}
} );
AlertDialog alert = builder.create();
alert.show();
}
}
}
// use to rotate captured image from device camera
public static int getImageOrientation(int rotation)
{
int angle = 0;
switch (rotation) {
case 0:
angle = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_90:
angle = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
angle = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
angle = 270;
break;
default:
break;
}
return angle;
}
I am getting image in landscape mode but not in potrait mode. Camera preview automatically rotates by 90 degrees after capturing image.
It is because of the image's EXIF data. You need to use a rotation method.
Depending on your build-in Camera orientation and orientation of device the pictures will have different rotations. You check the rotation of your particular image through ExifInterface.
/**
* #param filename Path to image file
* #param captureTime Time when image file was created
*/
public static int extractExifOrientationTagFromImageFile(String filename, long creationTime) {
/* The issue is on some devices, there's a bug that makes the picture taken saved in your app folder without proper
exif tags while a properly rotated image is saved in the android default folder (even though it shouldn't be).
Now what we do is recording the time when we're starting the camera app. Then we query
the Media Provider to see if any pictures were saved after this timestamp we've saved. That means most likely Android OS
saved the properly rotated picture in the default folder and of course put an entry in the media store and we can use the
rotation information from this row. */
int imageRotation = -1;
long imageFileSize = new File(filename).length();
Cursor mediaFileCursor = getContext().getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
new String[] { MediaStore.Images.ImageColumns.ORIENTATION, MediaStore.MediaColumns.SIZE },
MediaStore.MediaColumns.DATE_ADDED + " >= ?", new String[] { String.valueOf(creationTime / 1000 - 1) },
MediaStore.MediaColumns.DATE_ADDED + " DESC");
if((mediaFileCursor != null) && (mediaFileCursor.getCount() != 0)) {
while(mediaFileCursor.moveToNext()) {
long mediaFileSize = getLongFromCursor(mediaFileCursor, MediaStore.MediaColumns.SIZE);
// Extra check to make sure that we are getting the orientation from the proper file
if(mediaFileSize == imageFileSize) {
imageRotation = getIntFromCursor(mediaFileCursor, MediaStore.Images.ImageColumns.ORIENTATION);
break;
}
}
}
/* Now if the rotation at this point is still -1, then that means this is one of the devices with proper rotation information. */
if(imageRotation == -1) {
ExifInterface exif = null;
try {
exif = new ExifInterface(filename);
}
catch (IOException e) {
e.printStackTrace();
}
imageRotation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, -1);
}
return imageRotation;
}
private static final int COLUMN_NOT_EXISTS = -1;
public static Long getLongFromCursor(Cursor cursor, String columnName) {
int columnIndex;
if((columnIndex = cursor.getColumnIndex(columnName)) != COLUMN_NOT_EXISTS) {
return cursor.getLong(columnIndex);
}
else {
return null;
}
}
public static Integer getIntFromCursor(Cursor cursor, String columnName) {
int columnIndex;
if((columnIndex = cursor.getColumnIndex(columnName)) != COLUMN_NOT_EXISTS) {
return cursor.getInt(columnIndex);
}
else {
return null;
}
}
Now when you have your image rotation you can rotate it's bitmap properly:
int imageRotation = extractExifOrientationTagFromImageFile(lastCapturedMediaUriPath, cameraAppInvokeTime);
Matrix matrix = new Matrix();
switch(imageRotation) {
case ExifInterface.ORIENTATION_ROTATE_90:
matrix.postRotate(90);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
matrix.postRotate(180);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
matrix.postRotate(270);
break;
default:
break;
}
final Bitmap loadedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
Picture was taken successfully with camera but in portrait mode on samsung galaxy s3 the picture gets rotated. How can i solve this issue.
Camera intent is as follows:
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(xdestination));
startActivityForResult(intent, CAMERA_PIC_REQUEST);
In activity for result
if (requestCode==CAMERA_PIC_REQUEST){
// Bitmap bm = (Bitmap) data.getExtras().get("data");
Uri photo_uri = Uri.fromFile(xdestination);
Editer.PHOTO_FROM=11;
Bitmap decodeSampledBitmapFromFile=null;
try {
decodeSampledBitmapFromFile = decodeUri(photo_uri);
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
decodeSampledBitmapFromFile.compress(Bitmap.CompressFormat.JPEG,100, bytes);
File f = new File(Environment.getExternalStorageDirectory(), "user_image.jpg");
try {
if(f.exists())
f.delete();
f.createNewFile();
FileOutputStream fo = new FileOutputStream(f);
fo.write(bytes.toByteArray());
fo.close();
} catch (IOException e) {
e.printStackTrace( );
Log.d("ERROR", e.toString());
}
}
Pass your taken picture and SDCard path of that picture into the following method which will return the correct oriented picture...
private Bitmap imageOreintationValidator(Bitmap bitmap, String path) {
ExifInterface ei;
try {
ei = new ExifInterface(path);
int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
bitmap = rotateImage(bitmap, 90);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
bitmap = rotateImage(bitmap, 180);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
bitmap = rotateImage(bitmap, 270);
break;
}
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
private Bitmap rotateImage(Bitmap source, float angle) {
Bitmap bitmap = null;
Matrix matrix = new Matrix();
matrix.postRotate(angle);
try {
bitmap = Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(),
matrix, true);
} catch (OutOfMemoryError err) {
err.printStackTrace();
}
return bitmap;
}
Use :
public int getCameraPhotoOrientation(Context context, Uri imageUri, String imagePath){
int rotate = 0;
try {
context.getContentResolver().notifyChange(imageUri, null);
File imageFile = new File(imagePath);
ExifInterface exif = new ExifInterface(imageFile.getAbsolutePath());
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
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;
}
Log.i("RotateImage", "Exif orientation: " + orientation);
Log.i("RotateImage", "Rotate value: " + rotate);
} catch (Exception e) {
e.printStackTrace();
}
return rotate;
}
Try it like below.
File photo = new File(Environment.getExternalStorageDirectory(), "user_image.jpg");
if (photo.exists()) {
Bitmap myBitmap = BitmapFactory.decodeFile(photo
.getAbsolutePath());
imageView.setImageBitmap(myBitmap);
imageView.setRotation(90);
}
Step 1: Give a full path of your photo like File photo = new File(Environment.getExternalStorageDirectory()
, "Face.jpg");
Step 2: Check whether photo is exist or not if yes then set it to image view and rotate it to 90 degree.
You have no choice but read the image, rotate it and write the result back to SD card. The straightforward approach, using BitmapFactory, will easily run into OutOfMemory exception.
Alternatively, you can use JPEG lossless rotation, using jpegtran.
On SourceForge, there is a Java open source class LLJTran. The Android port is on GitHub.
Today I faced this problem. I know I'm late, but just in case someone needs it. In my case, if I pass the Uri inside the camera intent, then the output file was rotated. That is,
fun takePhoto() {
val intent = Intent(android.media.action.IMAGE_CAPTURE)
intent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(xdestination)) // <-- this line is the culprit for me
startActivityForResult(intent, CAMERA_PIC_REQUEST)
}
Then inside onActivity result, you get the bitmap rotated. I don't know why that happened.
So I didnot provide the Uri to the intent. That is I wrote this:
fun takePhoto() {
val intent = Intent(android.media.action.IMAGE_CAPTURE)
startActivityForResult(intent, CAMERA_PIC_REQUEST)
}
Therefore, inside onActivityResult I got the returned image as bitmap. Then I manually saved that bitmap inside the desired file / Uri.
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == PHOTO_CAPTURE_WITH_CAMERA_REQ_CODE && resultCode == RESULT_OK) {
// 1. handle the image as normal bitmap
val photo: Bitmap? = data?.extras?.get("data") as Bitmap;
// handleImage(SharedData.pendingPhotoUri.pop())
if (photo != null) {
// inside handle camera
handleCameraImage(photo)
};
}
}
private fun handleCameraImage(inputBitmap: Bitmap) {
//2. according to previous implementation, this uri should be the final output image file.
// 3. save the original bitmap in a temp image file
val tempBitmapFile: String = requireActivity().cacheDir.absolutePath +"/temp_photo_"+System.currentTimeMillis();
val fOuttemp: FileOutputStream = FileOutputStream(tempBitmapFile);
inputBitmap.compress(Bitmap.CompressFormat.PNG, 85, fOuttemp);
fOuttemp.flush();
fOuttemp.close();
// 4. use ExifInterface to make sure the photo is in right orientation.
val exifInterface: ExifInterface = ExifInterface(tempBitmapFile);
val orientation: Int = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_UNDEFINED);
Timber.tag(TAG).e("orientation == " + orientation);
var matrix = Matrix();
var isRotationNeeded: Boolean = true;
when(orientation){
ExifInterface.ORIENTATION_NORMAL -> {
Timber.tag(TAG).e("when ExifInterface.ORIENTATION_NORMAL");
// do nothing I guess
isRotationNeeded = false;
}
ExifInterface.ORIENTATION_ROTATE_90 -> {
Timber.tag(TAG).e("when ExifInterface.ORIENTATION_ROTATE_90");
matrix.setRotate(90f);
}
ExifInterface.ORIENTATION_ROTATE_180 -> {
Timber.tag(TAG).e("when ExifInterface.ORIENTATION_ROTATE_180");
matrix.setRotate(180f);
}
ExifInterface.ORIENTATION_ROTATE_270 -> {
Timber.tag(TAG).e("when ExifInterface.ORIENTATION_ROTATE_270");
matrix.setRotate(270f);
}
else -> {
Timber.tag(TAG).e("when else");
isRotationNeeded = false;
}
}
// if in wrong orientation,
// rotate image and save it in the file from step 2.
// else save the original image in the file from step 2.
lateinit var outputBitmap: Bitmap;
if(!isRotationNeeded) {
outputBitmap = inputBitmap;
}else{
outputBitmap = Bitmap.createBitmap(inputBitmap, 0, 0, inputBitmap.width,
inputBitmap.height, matrix, true);
}
val outputBitmapfile: File = File("your_awesome_file");
val fOut: FileOutputStream = FileOutputStream(outputBitmapfile);
outputBitmap.compress(Bitmap.CompressFormat.PNG, 85, fOut);
fOut.flush();
fOut.close();
var outputPhotoUri:Uri = getUriForFile(requireActivty(), outputBitmapfile);
// 5. finally use this photo / Uri to do whatever you want
}
fun getUriForFile(context: Context, file: File?): Uri? {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N || Config.ONLY_INTERNAL_STORAGE) {
try {
val destCopiedTempFile = File(context.getExternalFilesDir(null).toString() + File.separator + "temp")
FileBackend.copy(file, destCopiedTempFile)
FileProvider.getUriForFile(context,
BuildConfig.APPLICATION_ID + ".fileprovider", destCopiedTempFile)
} catch (e: IllegalArgumentException) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
throw SecurityException(e)
} else {
Uri.fromFile(file)
}
}
} else {
Uri.fromFile(file)
}
}
This worked for me.
This question already has answers here:
Why does an image captured using camera intent gets rotated on some devices on Android?
(23 answers)
Closed 4 years ago.
I'm working at an application in android which uses camera to take photos.For starting the camera I'm using an intent ACTION_IMAGE_CAPTURE like this:
Intent camera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File image=new File(Environment.getExternalStorageDirectory(),"PhotoContest.jpg");
camera.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(image));
imageUri=Uri.fromFile(image);
startActivityForResult(camera,1);
public void onActivityResult(int requestCode, int resultCode, Intent data){
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode){
case 1:
if (resultCode == Activity.RESULT_OK) {
selectedImage = imageUri;
getContentResolver().notifyChange(selectedImage, null);
image= (ImageView) findViewById(R.id.imageview);
ContentResolver cr = getContentResolver();
Bitmap bitmap;
try {
bitmap = android.provider.MediaStore.Images.Media
.getBitmap(cr, selectedImage);
image.setImageBitmap(bitmap);
Toast.makeText(this, selectedImage.toString(),
Toast.LENGTH_LONG).show();
} catch (Exception e) {
Toast.makeText(this, "Failed to load", Toast.LENGTH_SHORT)
.show();
Log.e("Camera", e.toString());
}
}
else
if(resultCode == Activity.RESULT_CANCELED) {
Toast.makeText(EditPhoto.this, "Picture could not be taken.", Toast.LENGTH_SHORT).show();
}
}
}
The problem is that all the photos that are taken are rotated with 90 degrees-horizontally aligned.
I've also put this into my manifest file:
<activity android:name=".EditPhoto">
android:screenOrientation="portrait"
</activity>
But still with no result!So can anyone help me???
http://developer.android.com/reference/android/media/ExifInterface.html
http://developer.android.com/reference/android/media/ExifInterface.html#TAG_ORIENTATION
So if in
Activity.onActivityResult(data, request, result) {
if (request == PHOTO_REQUEST && result == RESULT_OK) {
...
Uri imageUri = ...
File imageFile = new File(imageUri.toString());
ExifInterface exif = new ExifInterface(imageFile.getAbsolutePath());
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
int rotate = 0;
switch(orientation) {
case ExifInterface.ORIENTATION_ROTATE_270:
rotate-=90;
case ExifInterface.ORIENTATION_ROTATE_180:
rotate-=90;
case ExifInterface.ORIENTATION_ROTATE_90:
rotate-=90;
}
Canvas canvas = new Canvas(bitmap);
canvas.rotate(rotate);
}
Does this help at all?
Just to add to Greg's great answer, here's a whole "category" to do the job:
public static int neededRotation(File ff)
{
try
{
ExifInterface exif = new ExifInterface(ff.getAbsolutePath());
int orientation = exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
if (orientation == ExifInterface.ORIENTATION_ROTATE_270)
{ return 270; }
if (orientation == ExifInterface.ORIENTATION_ROTATE_180)
{ return 180; }
if (orientation == ExifInterface.ORIENTATION_ROTATE_90)
{ return 90; }
return 0;
} catch (FileNotFoundException e)
{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
}
return 0;
}
you'd use it more or less like this ...
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (requestCode == REQUEST_IMAGE_CAPTURE) // && resultCode == RESULT_OK )
{
try
{
Bitmap cameraBmp = MediaStore.Images.Media.getBitmap(
State.mainActivity.getContentResolver(),
Uri.fromFile( Utils.tempFileForAnImage() ) );
cameraBmp = ThumbnailUtils.extractThumbnail(cameraBmp, 320,320);
// NOTE incredibly useful trick for cropping/resizing square
// http://stackoverflow.com/a/17733530/294884
Matrix m = new Matrix();
m.postRotate( Utils.neededRotation(Utils.tempFileForAnImage()) );
cameraBmp = Bitmap.createBitmap(cameraBmp,
0, 0, cameraBmp.getWidth(), cameraBmp.getHeight(),
m, true);
yourImageView.setImageBitmap(cameraBmp);
// to convert to bytes...
ByteArrayOutputStream baos = new ByteArrayOutputStream();
cameraBmp.compress(Bitmap.CompressFormat.JPEG, 75, baos);
//or say cameraBmp.compress(Bitmap.CompressFormat.PNG, 0, baos);
imageBytesRESULT = baos.toByteArray();
} catch (FileNotFoundException e)
{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
}
return;
}
}
Hope it saves someone some typing in the future.
The above answer is very thorough, but I found I had to do a little bit more in order for every case to work, especially if you're dealing with images from other sources such as the Gallery or Google Photos. Here's my DetermineOrientation method. I have a utility class where this is located so I have to pass in the Activity in order to use managedQuery(which btw is deprecated so use cautiously). The reason I have to use two methods is because, depending on the source of the image, ExifInterface will not work. For instance, if I take a camera photo, Exif works fine. However, if I'm also choosing images from the Gallery or Google Drive, Exif does not work and always returns 0. Hope this helps someone.
public static int DetermineOrientation(Activity activity, Uri fileUri)
{
int orientation = -1;
int rotate = 0;
try {
ExifInterface exif = new ExifInterface(fileUri.getPath());
orientation = exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
rotate = 0;
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_270:
rotate = 270;
case ExifInterface.ORIENTATION_ROTATE_180:
rotate = 180;
case ExifInterface.ORIENTATION_ROTATE_90:
rotate = 90;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
if(rotate == 0)
{
String[] orientationColumn = {MediaStore.Images.Media.ORIENTATION};
Cursor cur = activity.managedQuery(fileUri, orientationColumn, null, null, null);
orientation = -1;
if (cur != null && cur.moveToFirst()) {
orientation = cur.getInt(cur.getColumnIndex(orientationColumn[0]));
}
if(orientation != -1)
{
rotate = orientation;
}
}
return rotate;
}