My image rotate when I use camera Intent . After capturing picture my I send this picture to another activity by using Intent and set this pic as background of Layout but capturing picture in landscape rotate the picture.
You can solve this problem by using the ExitInterface shown below:
private void setPic(Uri contentUri) throws IOException {
// Get the dimensions of the View
int targetW = uploadedImage.getWidth();
int targetH = uploadedImage.getHeight();
// Get the dimensions of the bitmap
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
// Decode the image file into a Bitmap sized to fill the View
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = calculateInSampleSize(bmOptions, targetW, targetH);
Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
bitmap = rotateImageIfRequired(bitmap, contentUri);
bitmap = ThumbnailUtils.extractThumbnail(bitmap, 750, 750);
uploadedImage.setImageBitmap(bitmap);
}
This function is where the bitmap is being decoded based on the path in the phone, it is then calling the rotateImageIfRequired() which will determine which way the image should rotate before it is set to the background of your layout. In this scenario uploadedImage is your layout.
private Bitmap rotateImageIfRequired(Bitmap img, Uri contentUri) throws IOException {
ExifInterface ei = new ExifInterface(contentUri.getPath());
int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
return rotateImage(img, 90);
case ExifInterface.ORIENTATION_ROTATE_180:
return rotateImage(img, 180);
case ExifInterface.ORIENTATION_ROTATE_270:
return rotateImage(img, 270);
default:
return img;
}
}
This function will determine which orientation the image is after it has been decoded and before it has been set.
private static Bitmap rotateImage(Bitmap img, int degree) {
Matrix matrix = new Matrix();
matrix.postRotate(degree);
Bitmap rotatedImg = Bitmap.createBitmap(img, 0, 0, img.getWidth(), img.getHeight(), matrix, true);
img.recycle();
return rotatedImg;
}
This function rotates the image and returns the new image.
Hope this helps.
Related
I am working on project where there is an need for image to be compressed and need get Uri for that compressed image. The problem is when I try to compress image from gallery it is creating one more image which is compressed along with the original image with different resolution how can achieve like I should have only one image reference in gallery that is also original image not the compressed image. Please find my code snippet below with which I have tried
public static Bitmap getResizedBitmap(Bitmap image, int maxSize) {
int width = image.getWidth();
int height = image.getHeight();
float bitmapRatio = (float) width / (float) height;
if (bitmapRatio > 1) {
width = maxSize;
height = (int) (width / bitmapRatio);
} else {
height = maxSize;
width = (int) (height * bitmapRatio);
}
return Bitmap.createScaledBitmap(image, width, height, true);
}
private static Bitmap rotateImage(Bitmap img, float degree) {
Matrix matrix = new Matrix();
matrix.postRotate(degree);
Bitmap rotatedImg = Bitmap.createBitmap(img, 0, 0, img.getWidth(), img.getHeight(), matrix, true);
//img.recycle();
return rotatedImg;
}
private static Bitmap rotateImageIfRequired(Context context, Bitmap img, Uri selectedImage) throws IOException {
InputStream input = context.getContentResolver().openInputStream(selectedImage);
ExifInterface ei;
if (Build.VERSION.SDK_INT > 23)
ei = new ExifInterface(input);
else
ei = new ExifInterface(selectedImage.getPath());
int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
return rotateImage(img, 90);
case ExifInterface.ORIENTATION_ROTATE_180:
return rotateImage(img, 180);
case ExifInterface.ORIENTATION_ROTATE_270:
return rotateImage(img, 270);
default:
return img;
}
}
public static Uri compressedImageUri(Uri selectedImage, Context context) {
try {
InputStream imageStream = null;
try {
imageStream = context.getContentResolver().openInputStream(
selectedImage);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Bitmap original = BitmapFactory.decodeStream(imageStream);
//Bitmap bmp = getResizedBitmap(original, 500);
Bitmap rotateBitmap = rotateImageIfRequired(context, original, selectedImage);
Bitmap bmp = getResizedBitmap(rotateBitmap, 500);
String path = MediaStore.Images.Media.insertImage(context.getContentResolver(), bmp, String.valueOf(System.currentTimeMillis()), null);
return Uri.parse(path);
} catch (Exception e) {
Log.d("error", e.getLocalizedMessage());
}
return null;
}
Use this Compressor.class
File imgFile = new File(uri.getPath());
File compressFile = Compressor.getDefault(getContext()).compressToFile(imgFile);
You may need some other class so please check compressor package.
Hope this will help you.
I have an app that the client has asked to add rotation support.
Below is the current code that takes the image from the camera.
camera.takePicture(null, null, new PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
if (data != null) {
Matrix mtx = new Matrix();
mtx.postRotate(180);
float density = Resources.getSystem().getDisplayMetrics().density;
Bitmap bm = BitmapFactory.decodeByteArray(data, 0, (data != null) ? data.length : 0);
Bitmap scaled = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), mtx, true);
bm = Bitmap.createScaledBitmap(scaled, (int)(480*density), (int)(320*density), true); //height and width are backwards because its portrait
previewImage(bm);
}
}
});
What I am trying to work out is the quickest way to work out what orientation the captured bitmap should be in, i.e when the user takes a picture with the device in landscape we need to flip:
Bitmap.createScaledBitmap(scaled, (int)(480*density), (int)(320*density), true);
to:
Bitmap.createScaledBitmap(scaled, (int)(320*density), (int)(480*density), true);
and also change the mtx.postRotate
My issue is working out the best way to find out what rotation the image was taken in.
Try this
private Bitmap checkForRotation(String filename, Bitmap bitmap) {
Bitmap myBitmap = bitmap;
ExifInterface ei = null;
try {
ei = new ExifInterface(filename);
new ExifInterface(filename);
} catch (IOException e) {
e.printStackTrace();
}
int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
//Here you get the orientation and do what ever you want to do with it as i am rotating the image
case ExifInterface.ORIENTATION_ROTATE_90:
myBitmap = rotateImage(bitmap, 90);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
myBitmap = rotateImage(bitmap, 180);
break;
}
return myBitmap;
}
In my app, the image is captured from the camera and then it displays in a ImageView I've done this approach successfully, but when my image is displayed in Imageview, Image display after rotate. I want to rotate Image and then Display in ImageView. When I click image from front camera then image is display proper with the help of bellow code
Matrix matrix = new Matrix();
matrix.postRotate(90);
Bitmap rotate = Bitmap.createBitmap(scale,0,0,scale.getWidth(),scale.getHeight(),matrix,true);
displayImage.setImageBitmap(rotate);
But when I click from back camera Image will display opposite to front camera.
One more thing when I click image from camera from different angle then image will display in ImageView in different angle.
I use following code in my application.
It works for me...!!!
File mediaFile = new File(mediaPath);
Bitmap bitmap;
if (mediaFile.exists()) {
if (isImage(mediaPath)) {
Bitmap myBitmap = BitmapFactory.decodeFile(mediaFile.getAbsolutePath());
int height = (myBitmap.getHeight() * 512 / myBitmap.getWidth());
Bitmap scale = Bitmap.createScaledBitmap(myBitmap, 512, height, true);
int rotate = 0;
try {
exif = new ExifInterface(mediaFile.getAbsolutePath());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_UNDEFINED);
switch (orientation) {
case ExifInterface.ORIENTATION_NORMAL:
rotate = 0;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
rotate = 270;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotate = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_90:
rotate = 90;
break;
}
Matrix matrix = new Matrix();
matrix.postRotate(rotate);
Bitmap rotateBitmap = Bitmap.createBitmap(scale, 0, 0, scale.getWidth(),
scale.getHeight(), matrix, true);
displayImage.setImageBitmap(rotateBitmap);
}
}
public static boolean isImage(String str) {
boolean temp = false;
String[] arr = { ".jpeg", ".jpg", ".png", ".bmp", ".gif" };
for (int i = 0; i < arr.length; i++) {
temp = str.endsWith(arr[i]);
if (temp) {
break;
}
}
return temp;
}
I need to upload photo from camera to server in my app. It works great on most of the devices. But a few devices are causing image to rotate by 90' which is not my desired behavior. After research, I came to know that its due to EXIF data attached with image. To strip EXIF data from the image bitmap, I tried various things like re-sizing image etc but none of them worked for me. Anybody please suggest a way to perform this task.
Try this,
public static Bitmap getImage(Context context, Uri uri)
throws FileNotFoundException, IOException {
InputStream input = context.getContentResolver().openInputStream(uri);
BitmapFactory.Options onlyBoundsOptions = new BitmapFactory.Options();
onlyBoundsOptions.inJustDecodeBounds = true;
onlyBoundsOptions.inDither = true;// optional
onlyBoundsOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;// optional
BitmapFactory.decodeStream(input, null, onlyBoundsOptions);
input.close();
if ((onlyBoundsOptions.outWidth == -1)
|| (onlyBoundsOptions.outHeight == -1))
return null;
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
bitmapOptions.inJustDecodeBounds = false;
bitmapOptions.inDither = true;
bitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;// optional
input = context.getContentResolver().openInputStream(uri);
Bitmap bitmap = BitmapFactory.decodeStream(input, null, bitmapOptions);
input.close();
ExifInterface ei = new ExifInterface(uri.getPath());
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;
}
return bitmap;
}
here uri is the uri of image taken from camera.
For understanding exif orienatation: goto http://www.impulseadventure.com/photo/exif-orientation.html
Here we use the ExifInterface object to read tags in a JPEG file and fetch the orientation attribute of image e.g.
// Variable to store the corrected bitmap.
Bitmap correctedBitMap = null;
ExifInterface exifInterface = new ExifInterface(<PATH OF YOUR PHOTO>);
int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
Now the integer variable orientation has the info about how much is the image rotated by, which is then checked against ExifInterface constant value & respectively the changes are made.
switch(orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
correctedBitMap = rotateImage(<YOUR BITMAP OBJECT>, 90);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
correctedBitMap = rotateImage(<YOUR BITMAP OBJECT>, 180);
break;
}
Here is the code for rotateImage method:
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 e) {
e.printStackTrace();
}
return bitmap;
}
I'm doing an app which takes a photo with the camera and then rotates it and scales it.
I need to rotate the image because the camera returns a wrong rotated image and I need to scale it to reduce its size.
I first save in a temp directory the original image returned by camera, then I read it and make modifications, saving the new image to a new file.
I tried using matrix to rotate and scale the picture, but it loses quality.
Then I tried to scale it first with Bitmap.createScaledBitmap and then rotate it with matrix, but the result is even uglier than the one using only matrix.
Then I tried to rotate it first and then resize it using always Bitmap.createScaledBitmap. The image doesn't lose quality, but it's stretched as I scaled it after rotating it and width and height are inverted. Tried also to invert height and width according to the rotation made, but it loses quality again.
This is the last code I've written:
in= new FileInputStream(tempDir+"/"+photo1_path);
out = new FileOutputStream(file+"/picture.png");
Bitmap src = BitmapFactory.decodeStream(in);
int iwidth = src.getWidth();
int iheight = src.getHeight();
int newWidth = 0;
int newHeight = 0;
newWidth = 800;
newHeight = 600;
// calculate the scale - in this case = 0.4f
float scaleWidth = ((float) newWidth) / iwidth;
float scaleHeight = ((float) newHeight) / iheight;
// createa matrix for the manipulation
Matrix matrix = new Matrix();
// resize the bit map
//matrix.postScale(scaleWidth, scaleHeight);
int orientation = getOrientation(MyActivity.this,Uri.parse(tempDir+"/"+photo1_path));
switch(orientation) {
case 3:
orientation = 180;
break;
case 6:
orientation = 90;
break;
case 8:
orientation = 270;
break;
}
int rotate = 0;
switch(orientation) {
case 90:
rotate=90;
break;
case 180:
rotate=180;
break;
case 270:
rotate=270;
break;
}
// rotate the Bitmap
matrix.postRotate(rotate);
src =Bitmap.createScaledBitmap(src , newWidth, newHeight, false);
// recreate the new Bitmap
Bitmap new_bit = Bitmap.createBitmap(src, 0, 0,
src.getWidth(), src.getHeight(), matrix, true);
new_bit.compress(Bitmap.CompressFormat.PNG, 100, out);
Any advice?
EDIT: If I only rotate or only scale the image, it doesn't lose quality. It's when I do both that the image loses quality. Also, if I put the image in an ImageView after resizing it and scaling it, it doesn't lose quality, it's just when I save it to file that loses quality.
Solved!
I 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);
//bm.compress(Bitmap.CompressFormat.PNG, 100, out);
/*Bitmap new_bit = Bitmap.createScaledBitmap(src , newWidth, newHeight, true);
new_bit.compress(Bitmap.CompressFormat.PNG, 100, out);*/
// recreate the new Bitmap
src = Bitmap.createBitmap(bm, 0, 0,bm.getWidth(), bm.getHeight(), matrix, true);
//Bitmap dest = Bitmap.createScaledBitmap(new_bit , newWidth, newHeight, true);
src.compress(Bitmap.CompressFormat.PNG, 100, out);
use this method to rotate the bitmap...
private Bitmap checkifImageRotated() {
ExifInterface exif;
try {
exif = new ExifInterface(file.getAbsolutePath());
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
int rotate = 0;
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_270 :
rotate = -90;
break;
case ExifInterface.ORIENTATION_ROTATE_180 :
rotate = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_90 :
rotate = 90;
break;
}
if (rotate != 0) {
Bitmap bitmap = BitmapFactory.decodeFile(getTempFile().getPath());
Matrix matrix = new Matrix();
matrix.setRotate(rotate);
Bitmap bmpRotated = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false);
recycle(bitmap);
return bmpRotated;
}
}
catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
Don't make the new bitmap just override
int angle=0; int valueangle=0; Bitmap bitmap;
#Override
public void onClick(View v) {
System.out.println("valueeeeeee " + angle);
if (bitmap != null) {
angle = valueangle + 90;
Matrix matrix = new Matrix();
matrix.postRotate(angle);
bitmap = Bitmap.createBitmap(
bitmap , 0, 0,
bitmap .getWidth(),
bitmap .getHeight(), matrix, true);
main_img.setImageBitmap(bitmap );
} else {
System.out.println(" bitmap is null");
}
}