I have a very simple layout with an ImageView. My application opens the camera, saves an image, and then displays the image in the ImageView with BitmapFactory.decodeFile
. The only issue is that it's rotated. I understand that a) this is due to the phone's camera defaulting to landscape, so this needs to be handled in code and b) image processing must be done in a separate thread from the UI.
The Android training documentation seems to be geared toward loading images from resource id's instead of file paths. This just throws a wrench in things as I'm able to follow the tutorials up to a point but ultimately have trouble reconciling the differences.
I'm certainly new at this so if someone could just give me a high-level overview of what needs to be done to accomplish this, I'd really appreciate it. The following code is where I'm currently adding the bitmap to the ImageView. I assume that my call to the separate thread would go in onCreate
?
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display_image);
Bitmap bm = BitmapFactory.decodeFile(MainActivity.image_path);
displayImageView = (ImageView) findViewById(R.id.myImageView);
displayImageView.setImageBitmap(bm);
}
Use ExifInterface for rotate
picturePath = getIntent().getStringExtra("path");
Bitmap bitmap = BitmapFactory.decodeFile(picturePath);
ExifInterface exif = new ExifInterface(picturePath);
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED);
Matrix matrix = new Matrix();
switch (orientation) {
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;
}
myImageView.setImageBitmap(bitmap);
bitmap.recycle();
Note : Here picturePath
is selected Image's path from Gallery
I was able to get it working with the following approach. I think you could do this without the AsyncTask but it seems that best practice states you should perform image processing in a non-UI thread (please feel free to correct - I'm quite new at this).
An improvement which could be made to this would be to handle the scaling in a more granular way. inSampleSize
is a great tool but it will only scale by powers of 2. Another improvement would be to initially only read the meta/EXIF data into bmOriginal
as the only use of this variable is to retrieve the height and width.
ImageView XML - pretty much standard. android:layout_width/height set to fill_parent
.
From the activity's java file -
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display_image);
new ImageRotator().execute(MainActivity.image_path);
}
private class ImageRotator extends AsyncTask<String, Void, Bitmap>{
protected Bitmap doInBackground(String... image_path){
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
bitmapOptions.inSampleSize = 4;
Bitmap bmOriginal = BitmapFactory.decodeFile(image_path[0], bitmapOptions);
Matrix matrix = new Matrix();
matrix.postRotate(90);
bmOriginal = Bitmap.createBitmap(bmOriginal, 0, 0, bmOriginal.getWidth(), bmOriginal.getHeight(), matrix, true);
return bmOriginal;
}
protected void onPostExecute(Bitmap result) {
myImageView = (ImageView) findViewById(R.id.myImageView);
myImageView.setImageBitmap(result);
}
}
The scaling process was found here and there's a great explanation of AsyncTask's features here.
Thanks so much to all who responded and again - please feel free to let me know if this is way off base or even if there's just a better way to do this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With