Save rotated Bitmap - android

itI take a picture from the camera and I simply want to save it with the correct orientation.
I know their is quite a few post about that subject but even after reading all the answers I got stuck to save my rotated Bitmap.
So here si my code:
Bitmap bitmap = BitmapFactory.decodeFile(pictureFile
.getAbsolutePath());
Matrix matrix = new Matrix();
matrix.postRotate(finalOrientation);
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, bitmap.getWidth(), bitmap.getHeight(), true);
Bitmap rotatedBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix, true);
findViewById(R.id.image_preview).setVisibility(View.VISIBLE);
((ImageView) findViewById(R.id.image_preview)).setImageBitmap(rotatedBitmap);
findViewById(R.id.surfaceView).setVisibility(View.GONE);
if(outputStream != null)
{
rotatedBitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
As you can see I show up my Bitmap image in an image view to be sure it's in the correct orientation and it is. But it's only when I save (compress) it that it returns to her original state.
Thank you in advance!

This is not an answer, but I want to post some code that might shed light on what is going on, and it does not fit into a comment:
ExifInterface exif;
int rotate = 0;
try {
exif = new ExifInterface (file.getAbsolutePath());
int exifOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
switch (exifOrientation) {
case ExifInterface.ORIENTATION_ROTATE_90: rotate = 1 /*90*/; break;
case ExifInterface.ORIENTATION_ROTATE_180: rotate = 2 /*180*/; break;
case ExifInterface.ORIENTATION_ROTATE_270: rotate = 3 /*270*/; break;
}
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Log.d(TAG,"~~~~~~ exifOrientation: rotate="+rotate);

Related

How can I edit My image EXIF data for image rotation

In my app the user gets an image from the camera or gallery, these images are then converted to a PDF Now my Problem is on some devices the image captured by the Camera is rotated 90 degrees, the devices are some samsung devices specifically an S7,
I know I need to edit the EXIF data of the image but I am new to android, and the entire EXIF data thing goes over my head completely any help would be aprecieated
This is where I call the selected image and convert it to a PDF
PdfDocument document=new PdfDocument();
// crate a page description
PdfDocument.PageInfo pageInfo;
PdfDocument.Page page;
Canvas canvas;
int i;
Bitmap image;
for (i=0; i < list.size(); i++) {
pageInfo=new PdfDocument.PageInfo.Builder(992, 1432, 1).create();
page=document.startPage(pageInfo);
canvas=page.getCanvas();
image=BitmapFactory.decodeFile(list.get(i));
image = Bitmap.createScaledBitmap(image, 980, 1420, true);
image.setDensity(DisplayMetrics.DENSITY_300);
canvas.setDensity(DisplayMetrics.DENSITY_300);
canvas.drawBitmap(image, 0, 0, null);
document.finishPage(page);
}
#SuppressWarnings("deprecation") String directory_path=Environment.getExternalStorageDirectory().getPath() + "/mypdf/";
File file=new File(directory_path);
if (!file.exists()) {
//noinspection ResultOfMethodCallIgnored
file.mkdirs();
}
#SuppressLint("SimpleDateFormat") String timeStamp=(new SimpleDateFormat("yyyyMMdd_HHmmss")).format(new Date());
String targetPdf=directory_path + timeStamp + ".pdf";
File filePath=new File(targetPdf);
try {
document.writeTo(new FileOutputStream(filePath));
} catch (IOException e) {
Log.e("main", "error " + e.toString());
Toasty.error(this, "Error making PDF" + e.toString(), Toast.LENGTH_LONG).show();
}
// close the document
document.close();
Add this to your build gradle:
implementation 'androidx.exifinterface:exifinterface:1.0.0'
get rotation data:
Bitmap bitmap = BitmapFactory.decodeFile(path);
ExifInterface exif;
try {
exif = new ExifInterface(path);
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_UNDEFINED);
Bitmap bmRotated = MyUtility.rotateBitmap(bitmap, orientation);
}
} catch (IOException e) {
e.printStackTrace();
}
rotateBitmap() method:
public static Bitmap rotateBitmap(Bitmap bitmap, int orientation) {
Matrix matrix = new Matrix();
switch (orientation) {
case ExifInterface.ORIENTATION_NORMAL:
mLog.i(TAG,"normal");
return bitmap;
case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
mLog.i(TAG,"ORIENTATION_FLIP_HORIZONTAL");
matrix.setScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
mLog.i(TAG,"ORIENTATION_ROTATE_180");
matrix.setRotate(180);
break;
case ExifInterface.ORIENTATION_FLIP_VERTICAL:
mLog.i(TAG,"ORIENTATION_FLIP_VERTICAL");
matrix.setRotate(180);
matrix.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_TRANSPOSE:
matrix.setRotate(90);
matrix.postScale(-1, 1);
mLog.i(TAG,"ORIENTATION_TRANSPOSE");
break;
case ExifInterface.ORIENTATION_ROTATE_90:
matrix.setRotate(90);
mLog.i(TAG,"ORIENTATION_ROTATE_90");
break;
case ExifInterface.ORIENTATION_TRANSVERSE:
mLog.i(TAG,"ORIENTATION_TRANSVERSE");
matrix.setRotate(-90);
matrix.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
matrix.setRotate(-90);
mLog.i(TAG,"ORIENTATION_ROTATE_270");
break;
default:
mLog.i(TAG,"UNKNOWN");
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;
}
}
Although I have had problems on a few samsung devices this works well. Give it a try.

Detect which orientation a bitmap taken from the camera should be

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;
}

How to strip EXIF data from Android Camera image

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;
}

Image oriention issue capture from camera

I was facing a problem image capture from camera it was showing image in landscape even though i capture that image in portrait then i found code online. But i think there is some problem with this code it sometimes didn't work (show image in landscape). So what's wrong there
private void adjustImageOrientation()
{
ExifInterface exif;
int rotate = 0;
try
{
exif = new ExifInterface(filepath);
int exifOrientation = exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
switch (exifOrientation)
{
case ExifInterface.ORIENTATION_ROTATE_90:
rotate = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotate = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
rotate = 270;
break;
}
if (rotate != 0)
{
int w = bitmap.getWidth();
int h = bitmap.getHeight();
// Setting pre rotate
Matrix mtx = new Matrix();
mtx.preRotate(rotate);
// Rotating Bitmap & convert to ARGB_8888, required by tess
try
{
bitmap = Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, false);
}
catch(OutOfMemoryError e)
{
e.printStackTrace();
//image = Bitmap.createBitmap(image, 0, 0, w/2, h/2, mtx, false);
}
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
// return image.copy(Bitmap.Config.ARGB_8888, true);
}

Rotating of large image causes OutOfMemoryError

I'm trying to rotate the image taken from camera and save it without scaling down without showing in an view, but when I try to load it like this
Bitmap bmp = BitmapFactory.decodeFile(tmpImageFilePath);
I get OutOfMemoryError. There is no problem for me to rotate image but how to load it and save with original size? I've already googled some techniques in order to solve this problem but none of them fits me.
And when I try this variant:
File f = new File(tmpImageFilePath);
long filesize = f.length();
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(angle);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap bmp = BitmapFactory.decodeFile(tmpImageFilePath, options);
Bitmap correctBmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), mat, true);
bmp.recycle();
try {
FileOutputStream out = new FileOutputStream(f);
correctBmp.compress(Bitmap.CompressFormat.JPEG, 90, out);
} catch (Exception e) {
e.printStackTrace();
}
I get lesser image.

Categories

Resources