Facing Orientation issue with Camera captured image on Android phones - android

I am using exifInterface for photo rotation issue code is below: Facing captured image orientation issue from camera.
Create a Bitmap from the file
Bitmap b = BitmapFactory.decodeFile(imagePath);
Resize the Bitmap by scaling it to appropriate level
int width = b.getWidth();
int height = b.getHeight();
int newWidth = 150;
int newHeight = 150;
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
// Bitmap resizedBitmap = Bitmap.createBitmap(b, 0, 0, width, height, matrix, true);
// resizedBitmap.compress(Bitmap.CompressFormat.JPEG, 70, out);
Handle orientation of the image
ExifInterface exif = new ExifInterface(imagePath);
String orientation = exif.getAttribute(ExifInterface.TAG_ORIENTATION);
if (orientation.equals(ExifInterface.ORIENTATION_NORMAL)) {
// Do nothing. The original image is fine.
} else if (orientation.equals(ExifInterface.ORIENTATION_ROTATE_90+"")) {
matrix.postRotate(90);
} else if (orientation.equals(ExifInterface.ORIENTATION_ROTATE_180+"")) {
matrix.postRotate(180);
} else if (orientation.equals(ExifInterface.ORIENTATION_ROTATE_270+"")) {
matrix.postRotate(270);
}
Save the new bitmap
out = new FileOutputStream(new File("some output file path"));
Bitmap resizedBitmap = Bitmap.createBitmap(b, 0, 0, width, height, matrix, true);
resizedBitmap.compress(Bitmap.CompressFormat.JPEG, 70, out);
This code not working for resolve rotation issue, please give me guideline.
On Lg devices it's exifinterface always returning 0 orientation, Samsung devices returning 6 and 1.
How to fix this issue with all the devices like htc, Motorola, samsung , Sony and LG.
I am thankful to you all please help me.

You can use this function to do the same thing you require. Have this function in your activity or any util class and call it to get bitmap from file path.
I have been using this function in my application and my prime testing devices are LG.
public static Bitmap decodeFile(String path) {
int orientation;
try {
if (path == null) {
return null;
}
// decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
// Find the correct scale value. It should be the power of 2.
final int REQUIRED_SIZE = 70;
int width_tmp = o.outWidth, height_tmp = o.outHeight;
int scale = 8;
while (true) {
if (width_tmp / 2 < REQUIRED_SIZE
|| height_tmp / 2 < REQUIRED_SIZE)
break;
width_tmp /= 2;
height_tmp /= 2;
scale++;
}
// decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
Bitmap bm = BitmapFactory.decodeFile(path, o2);
Bitmap bitmap = bm;
ExifInterface exif = new ExifInterface(path);
orientation = exif
.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
Log.e("orientation", "" + orientation);
Matrix m = new Matrix();
if ((orientation == 3)) {
m.postRotate(180);
m.postScale((float) bm.getWidth(), (float) bm.getHeight());
// if(m.preRotate(90)){
Log.e("in orientation", "" + orientation);
bitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(),
bm.getHeight(), m, true);
return bitmap;
} else if (orientation == 6) {
m.postRotate(90);
Log.e("in orientation", "" + orientation);
bitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(),
bm.getHeight(), m, true);
return bitmap;
}
else if (orientation == 8) {
m.postRotate(270);
Log.e("in orientation", "" + orientation);
bitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(),
bm.getHeight(), m, true);
return bitmap;
}
return bitmap;
} catch (Exception e) {
}
return null;
}

Related

How to display Bitmap correctly?

I'm coping with two issues trying to display a photo from the Gallery in my Android application. What I want to do is simple: get a photo from the gallery and put it in a ImageView (which is 100dp*100dp) in my MainActivity.
The first issue is that on some phones, such as Sony Xperia, the photo is rotated when it is set on the ImageView. To address the problem, I found that piece of code in a SO answer:
public Bitmap decodeFile(String path)
{
int orientation;
try {
if (path == null) {
return null;
}
// decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
// Find the correct scale value. It should be the power of 2.
final int REQUIRED_SIZE = 70;
int width_tmp = o.outWidth, height_tmp = o.outHeight;
int scale = 0;
while (true) {
if (width_tmp / 2 < REQUIRED_SIZE
|| height_tmp / 2 < REQUIRED_SIZE)
break;
width_tmp /= 2;
height_tmp /= 2;
scale++;
}
// decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
Bitmap bm = BitmapFactory.decodeFile(path, o2);
Bitmap bitmap = bm;
ExifInterface exif = new ExifInterface(path);
orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
Log.e("ExifInteface .........", "rotation =" + orientation);
// exif.setAttribute(ExifInterface.ORIENTATION_ROTATE_90, 90);
Log.e("orientation", "" + orientation);
Matrix m = new Matrix();
if ((orientation == ExifInterface.ORIENTATION_ROTATE_180)) {
m.postRotate(180);
// m.postScale((float) bm.getWidth(), (float) bm.getHeight());
// if(m.preRotate(90)){
Log.e("in orientation", "" + orientation);
bitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(),
bm.getHeight(), m, true);
return bitmap;
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_90) {
m.postRotate(90);
Log.e("in orientation", "" + orientation);
bitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(),
bm.getHeight(), m, true);
return bitmap;
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) {
m.postRotate(270);
Log.e("in orientation", "" + orientation);
bitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(),
bm.getHeight(), m, true);
return bitmap;
}
return bitmap;
} catch (Exception e) {
return null;
}
}
That works perfectly, but I also want the image to be a square, which is not the case for now.
To do that, after I used the first method on my bitmap, I also called that one:
public static Bitmap cropToSquare(Bitmap bitmap)
{
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int newWidth = (height > width) ? width : height;
int newHeight = (height > width)? height - ( height - width) : height;
int crop = (width - height) / 2;
crop = (crop < 0)? 0: crop;
Bitmap cropImg = Bitmap.createBitmap(bitmap, crop, 0, newWidth, newHeight);
return cropImg;
}
It does turns the bitmap into a square, but the problem is it cuts the photo instead of rescaling it. (basically half of the image is lost)
I am pretty sure what I want to do is simple, how can I do that?
Instead of using,
Bitmap.createBitmap(bitmap, crop, 0, newWidth, newHeight);
Use this below line,
Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, false);
Anyway, the official document is the best teacher, check here

ImageView Bitmaps are incorrectly oriented

I've seen several questions regarding this topic, but none that address my problem.
I dynamically create ImageViews and allow the user to take/add photos of items for an inventory. The following code exists to generate the Bitmap and populate the ImageView:
protected void addPhotosToView(ArrayList<String> uris) {
for (String uriString : uris) {
try {
Uri uri = Uri.parse(uriString);
File imageFile = new File(uri.getPath());
int orientation = resolveBitmapOrientation(imageFile);
Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);
bitmap = applyOrientation(bitmap, orientation);
ImageView image = new ImageView(ItemActivity.this);
int h = 100; // height in pixels
int w = 100; // width in pixels
Bitmap scaled = Bitmap.createScaledBitmap(bitmap, h, w, true);
image.setImageBitmap(scaled);
LinearLayout photoLayout = (LinearLayout) findViewById(R.id.itemPhotoLayout);
photoLayout.addView(image);
addClickListener(image, uri);
} catch (Exception e) {
e.printStackTrace();
}
}
}
But once the image is added or taken, some images appear with the wrong orientation. Some of the photos stored in the phone in portrait are displayed in portrait, while others appear to be in landscape. Landscape photos are equally arbitrary.
This does not appear to be happening on all devices (the device that I'm seeing this on is a Samsung S4)
As you can see in the code, I have tried getting/applying orientation changes using Exif tags, but I'm always getting 0 for the orientation with this device and have not seen any answers for questions that ask for a solution when orientation is always 0.
I'm looking to ship this software soon and need some sort of workaround or solution, so I'm willing to accept some other way of going from Uris/strings to a dynamic, horizontally scrollable list of properly oriented images if this can't be resolved any other way.
you need to decode the bitmap that's all try this tutorial you can download the source.
that application dose exactly what you want maybe it will help you i hope because it worked fine with my application
Please use this method to show/decode your bitmap. It is taken from another SO post I cant remember which and is modified for my use. This method returns bitmap according to the exif orientation data if present on the image:
public Bitmap decodeFile(String path) {// you can provide file path here
int orientation;
try {
if (path == null) {
return null;
}
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
// Find the correct scale value. It should be the power of 2.
final int REQUIRED_SIZE = 70;
// final int REQUIRED_SIZE = 20;
int width_tmp = o.outWidth, height_tmp = o.outHeight;
int scale = 0;
while (true) {
if (width_tmp / 2 < REQUIRED_SIZE
|| height_tmp / 2 < REQUIRED_SIZE)
break;
width_tmp /= 2;
height_tmp /= 2;
scale++;
}
// decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
Bitmap bm = BitmapFactory.decodeFile(path, o2);
Bitmap bitmap = bm;
ExifInterface exif = new ExifInterface(path);
orientation = exif
.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
Matrix m = new Matrix();
if ((orientation == ExifInterface.ORIENTATION_ROTATE_180)) {
m.postRotate(180);
bitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(),
bm.getHeight(), m, true);
photo(bitmap, path);
return bitmap;
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_90) {
m.postRotate(90);
bitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(),
bm.getHeight(), m, true);
photo(bitmap, path);
return bitmap;
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) {
m.postRotate(270);
bitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(),
bm.getHeight(), m, true);
photo(bitmap, path);
return bitmap;
}
return bitmap;
} catch (Exception e) {
return null;
}
}

How to get an image with full clarity?

I tried loading images from sdcard camera folder,after loading I created bitmap by using scaled bitmap,in that I want to show only some portions of image so I tried using createBitmap() to create a new bitmap,but it is still getting blurred, how can i solve this problem?
File[] files = targetDirector.listFiles();
for (File file : files) {
String path = file.getAbsolutePath();
itemList.add(path);
if (myBitmap != null) {
myBitmap = null;
}
myBitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
System.out.println("thumbnails1 width: " + myBitmap.getWidth());
System.out.println("thumbnails1 height: " + myBitmap.getHeight());
myBitmap = Bitmap.createScaledBitmap(myBitmap, 150, 150, false);
ExifInterface exif;
try {
exif = new ExifInterface(file.getAbsolutePath());
String orientString = exif
.getAttribute(ExifInterface.TAG_ORIENTATION);
int orientation = orientString != null ? Integer
.parseInt(orientString)
: ExifInterface.ORIENTATION_NORMAL;
int rotationAngle = 0;
if (orientation == ExifInterface.ORIENTATION_ROTATE_90) {
System.out.println("photopotart");
rotationAngle = 90;
System.out.println("myBitmap" + myBitmap.getWidth());
System.out.println("myBitmap" + myBitmap.getHeight());
myBitmap = Bitmap.createScaledBitmap(myBitmap, 150, 150,
false);
Matrix matrix = new Matrix();
matrix.postRotate(90);
myBitmap = Bitmap.createBitmap(myBitmap, 0, 0,
150, 150, matrix,
true);
myBitmap = Bitmap.createBitmap(myBitmap, 0, 0, 150, 100 );
myBitmap = highlightImage(myBitmap);
photsList.add(myBitmap);
}
else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) {
System.out.println("180 angle");
rotationAngle = 180;
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) {
System.out.println("other 270");
rotationAngle = 270;
} else {
System.out.println("photolandscape");
myBitmap = Bitmap.createScaledBitmap(myBitmap, 150, 150,
false);
myBitmap = Bitmap.createBitmap(myBitmap, 30, 0, 120, 150);
photsList.add(myBitmap);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
My xml file is:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<ImageView
android:id="#+id/img"
android:layout_width="150dip"
android:layout_height="150dip" />
</LinearLayout>
Use the following method for decoding your file path.
public void decodeFile(String filePath) {
// Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, o);
// The new size we want to scale to
final int REQUIRED_SIZE = 1024;
// Find the correct scale value. It should be the power of 2.
int width_tmp = o.outWidth, height_tmp = o.outHeight;
int scale = 2;
while (true) {
if (width_tmp < REQUIRED_SIZE && height_tmp < REQUIRED_SIZE)
break;
width_tmp /= 2;
height_tmp /= 2;
scale *= 2;
}
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
bmp = BitmapFactory.decodeFile(filePath, o2); // this bmp object of Bitmap is global and you can set it to your ImageView.
}
Now you can call this function replace with this one
myBitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
to
decodeFile(file.getAbsolutePath());
You can set your scale variable according to your requirement that you can get your image with very good clarity.

poor image quality after saving rotated bitmap to sdcard

I am making an app where in one of the activity i am fetching image from gallery and showing it in adapter like image below
I have to rotate that image and save it to sdcard. My code is doing fine but after saving it to sdcard i get very poor quality of image. my code is:
viewHolder.imgViewRotate.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
imagePosition = (Integer) v.getTag();
Matrix matrix = new Matrix();
matrix.postRotate(90);
Bitmap rotated = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
try {
FileOutputStream out = new FileOutputStream(new File(uriList.get(rotatePosition).toString()));
rotated.compress(Bitmap.CompressFormat.PNG, 100, out);
out.close();
} catch (Exception e) {
e.printStackTrace();
}
notifyDataSetChanged();
}
});
Any suggestions will be great help.
Try out below code to reduce image size without losing its quality:
public Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth)
{
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// create a matrix for the manipulation
Matrix matrix = new Matrix();
// resize the bit map
matrix.postScale(scaleWidth, scaleHeight);
// recreate the new Bitmap
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false);
return resizedBitmap;
}
EDITED:
Resize the image using BitmapFactory inSampleSize option and the image doesn't lose quality at all. Code:
BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
bmpFactoryOptions.inJustDecodeBounds = true;
Bitmap bm = BitmapFactory.decodeFile(tempDir+"/"+photo1_path , bmpFactoryOptions);
int heightRatio = (int)Math.ceil(bmpFactoryOptions.outHeight/(float)600);
int widthRatio = (int)Math.ceil(bmpFactoryOptions.outWidth/(float)800);
if (heightRatio > 1 || widthRatio > 1)
{
if (heightRatio > widthRatio){
bmpFactoryOptions.inSampleSize = heightRatio;
} else {
bmpFactoryOptions.inSampleSize = widthRatio;
}
}
bmpFactoryOptions.inJustDecodeBounds = false;
bm = BitmapFactory.decodeFile(tempDir+"/"+photo1_path, bmpFactoryOptions);
// recreate the new Bitmap
src = Bitmap.createBitmap(bm, 0, 0,bm.getWidth(), bm.getHeight(), matrix, true);
src.compress(Bitmap.CompressFormat.PNG, 100, out);

Capture photo rotate 90 degree in samsung mobile

Photo is rotating 90 degree while capturing from camera in samsung mobile rest of other mobiles(HTC) its working fine. Please help me for this.
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, IMAGE_CAPTURE);
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
try
{
if (requestCode == IMAGE_CAPTURE) {
if (resultCode == RESULT_OK){
Uri contentUri = data.getData();
if(contentUri!=null)
{
String[] proj = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
imageUri = Uri.parse(cursor.getString(column_index));
}
tempBitmap = (Bitmap) data.getExtras().get("data");
mainImageView.setImageBitmap(tempBitmap);
isCaptureFromCamera = true;
}
}
Some device rotate image according to device orientation .
here i have write one common method to get orientation and get image in right scale
public Bitmap decodeFile(String path) {//you can provide file path here
int orientation;
try {
if (path == null) {
return null;
}
// decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
// Find the correct scale value. It should be the power of 2.
final int REQUIRED_SIZE = 70;
int width_tmp = o.outWidth, height_tmp = o.outHeight;
int scale = 0;
while (true) {
if (width_tmp / 2 < REQUIRED_SIZE
|| height_tmp / 2 < REQUIRED_SIZE)
break;
width_tmp /= 2;
height_tmp /= 2;
scale++;
}
// decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
Bitmap bm = BitmapFactory.decodeFile(path, o2);
Bitmap bitmap = bm;
ExifInterface exif = new ExifInterface(path);
orientation = exif
.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
Log.e("ExifInteface .........", "rotation ="+orientation);
// exif.setAttribute(ExifInterface.ORIENTATION_ROTATE_90, 90);
Log.e("orientation", "" + orientation);
Matrix m = new Matrix();
if ((orientation == ExifInterface.ORIENTATION_ROTATE_180)) {
m.postRotate(180);
// m.postScale((float) bm.getWidth(), (float) bm.getHeight());
// if(m.preRotate(90)){
Log.e("in orientation", "" + orientation);
bitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(),
bm.getHeight(), m, true);
return bitmap;
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_90) {
m.postRotate(90);
Log.e("in orientation", "" + orientation);
bitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(),
bm.getHeight(), m, true);
return bitmap;
}
else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) {
m.postRotate(270);
Log.e("in orientation", "" + orientation);
bitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(),
bm.getHeight(), m, true);
return bitmap;
}
return bitmap;
} catch (Exception e) {
return null;
}
}
EDIT:
This code is not optimized , i just show the logic code from my one of the test project.
Another thing you can add to the above solutions is "samsung".contentEquals(Build.MANUFACTURER). If you know that your problem is only with Samsung devices you could be reasonably sure that you need to rotate the image returned (only) if ("samsung".contentEquals(Build.MANUFACTURER) && getActivity().getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT // && width > height//) // here you know you need to rotate
You could be "reasonably" confident that the rotation is warranted then.
public static Bitmap rotateBitmap(Bitmap b, float degrees) {
Matrix m = new Matrix();
if (degrees != 0) {
// clockwise
m.postRotate(degrees, (float) b.getWidth() / 2,
(float) b.getHeight() / 2);
}
try {
Bitmap b2 = Bitmap.createBitmap(b, 0, 0, b.getWidth(),
b.getHeight(), m, true);
if (b != b2) {
b.recycle();
b = b2;
}
} catch (OutOfMemoryError ex) {
// We have no memory to rotate. Return the original bitmap.
}
return b;
}
If it's really a bug then you may have to manually rotate it back to landscape. Bitmap data always has a width and a height, just take a look at the numbers and if the width is less than the height rotate the image as per alistair3408's answer.

Categories

Resources