I need to get image from sd card, create, rotate and save changed image.
I try to use this code
Bitmap original = BitmapFactory.decodeFile(file.getAbsolutePath());
ExifInterface originalExif = new ExifInterface(file.getAbsolutePath());
int orientation = originalExif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED);
Matrix matrix = new Matrix();
int rotate = 90;
if(orientation == ExifInterface.ORIENTATION_ROTATE_90){
rotate = 180;
}else if(orientation == ExifInterface.ORIENTATION_ROTATE_180){
rotate = 270;
}else if(orientation == ExifInterface.ORIENTATION_ROTATE_270){
rotate = 0;
}
matrix.postRotate(rotate);
Bitmap bitmap = Bitmap.createBitmap(original, 0, 0, original.getWidth(), original.getHeight(), matrix, true);
try {
FileOutputStream out = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
original.recycle();
bitmap.recycle();
}
ExifInterface newExif = new ExifInterface(file.getAbsolutePath());
newExif.setAttribute(ExifInterface.TAG_ORIENTATION, String.valueOf(ExifInterface.ORIENTATION_ROTATE_90));
newExif.saveAttributes();
But i cant save change in ExifInterface. This just clear all the tags.
saveAttributes method only Save the tag data into the JPEG file.
check this link
http://developer.android.com/reference/android/media/ExifInterface.html#saveAttributes()
So if you change your code this
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
to this
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
it will save you exif tag data
Hope this help
Let me know in case of any other issue
Related
I am selecting an image from gallery and showing it on a image view. Image is getting selected, but on samsung phones it has issue of rotating the image so to solve that I am checking if the image is rotated or not usif EXIF interface and if rotated change its angle.
But this is not working for some images. Some images I can see straight, but some images if they are straight then also they are getting rotate.
As I did debug the orientation for the image is 0, it goes in the default case and applies normal bitmap to the rotated bitmap. Still the image I see is rotated. Not getting why is this happening..
private void onSelectFromGalleryResult(Intent data) {
Bitmap bm=null;
if (data != null) {
try {
bm = MediaStore.Images.Media.getBitmap(getApplicationContext().getContentResolver(), data.getData());
} catch (IOException e) {
e.printStackTrace();
}
}
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
bm = Bitmap.createScaledBitmap(bm,512,512, true);
bm.compress(Bitmap.CompressFormat.PNG,100, bytes);
File destination = new File(Environment.getExternalStorageDirectory(),
System.currentTimeMillis() + ".png");
FileOutputStream fo;
try {
destination.createNewFile();
fo = new FileOutputStream(destination);
fo.write(bytes.toByteArray());
fo.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
loadImageFromFile(destination.getAbsolutePath());
}
public void loadImageFromFile(String imageFile){
try {
ExifInterface ei = new ExifInterface(imageFile);
int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_UNDEFINED);
Bitmap bitmap = BitmapFactory.decodeFile(imageFile);
Bitmap rotatedBitmap = null;
Log.e("orientation",String.valueOf(orientation)+" check");
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
rotatedBitmap = rotateImage(bitmap, 90);
Log.e("orientation",String.valueOf(orientation)+" check");
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotatedBitmap = rotateImage(bitmap, 180);
Log.e("orientation",String.valueOf(orientation)+" check");
break;
case ExifInterface.ORIENTATION_ROTATE_270:
rotatedBitmap = rotateImage(bitmap, 270);
Log.e("orientation",String.valueOf(orientation)+" check");
break;
case ExifInterface.ORIENTATION_NORMAL:
rotatedBitmap = bitmap;
Log.e("orientation",String.valueOf(orientation)+" check");
break;
default:
rotatedBitmap = bitmap;
Log.e("orientation",String.valueOf(orientation)+" check");
break;
}
if(rotatedBitmap != null)
{
profile_image.setImageBitmap(rotatedBitmap);
selectedBitmap = rotatedBitmap;
ByteArrayOutputStream stream = new ByteArrayOutputStream();
selectedBitmap.compress(Bitmap.CompressFormat.PNG, 100, stream); //replace 100 with desired quality percentage.
byte[] byteArray = stream.toByteArray();
File tempFile = File.createTempFile("temp",null, getCacheDir());
FileOutputStream fos = new FileOutputStream(tempFile);
fos.write(byteArray);
mProfileImage = tempFile;
}
}
catch (IOException ex) {
// UiUtils.showAlert(getString(R.string.error),NewGroupAcvitity.this);
}
}
public static Bitmap rotateImage(Bitmap source, float angle) {
Matrix matrix = new Matrix();
matrix.postRotate(angle);
return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix,
true);
}
EDIT:
-
#SuppressWarnings("deprecation")
- private void onSelectFromGalleryResult(Intent data) {
-
- Uri uri = (Uri)data.getData();
- String[] filePathColumn = { MediaStore.Images.Media.DATA };
- Cursor cursor = getContentResolver().query(uri,filePathColumn, null, null, null);
- if(cursor != null) {
- cursor.moveToFirst();
- int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
- String picturePath = cursor.getString(columnIndex);
- cursor.close();
-
- loadImageFromFile(picturePath);
- }
- }
#greenapps - use selected file like this? I tried this, but this was not working in xiaomi devices so I changed the code. Is there any other way for other devices?
What's going wrong here? Can anyone help please? Thank you.
loadImageFromFile(destination.getAbsolutePath());
The image that you try to load is originally from a bitmap which you compressed to jpg and saved to file. destination is the File object for that file.
Bitmaps do not contain exif information. And hence your jpg file will not contain an exif too.
So it is useless to use ExifInterface on it.
Sid i saw this code before. And told the same story. Maybe it was even you which i told it.
I would like to rotate and save the rotated image and move it elsewhere within my android device.
I am able to rotate my image and set it to image view.
I can copy an UN-ROTATED image to a destination of my choice.
The only thing I am unable to do is get the saved rotated image FILE (rotated.jpg)
My code below to rotate: (this does not save rotated file to storage?)
Bitmap bmp = BitmapFactory.decodeFile(filePathLocal);
Matrix matrix = new Matrix();
matrix.postRotate(getImageOrientation(filePathLocal));
rotatedBitmap = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);
//Set Image
ImageButton ibProfile = (ImageButton) findViewById(R.id.ibProfile);
ibProfile.setImageBitmap(rotatedBitmap);
Now the above only rotates temporarily until the activity is ended, now I would like to save this rotated image from above code and move it somehwere before uploading it to server, I already know how to copy/move files and upload so no need to post those codes - all I need is the code for SAVING ROTATED IMAGE, so that I have something like /sdcard/saved_rotated_image.jpg
Bitmap bmp = BitmapFactory.decodeFile(filePathLocal);
Matrix matrix = new Matrix();
matrix.postRotate(getImageOrientation(filePathLocal));
rotatedBitmap = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, false);
//Set Image
ImageButton ibProfile = (ImageButton) findViewById(R.id.ibProfile);
ibProfile.setImageBitmap(rotatedBitmap);
Put false in the createbitmap's last argument
Refere my code:
#Override
protected Uri doInBackground(String... params) {
String filepath = params[0];
String filename = params[1];
String filetype = params[2];
Bitmap bitmap = takeScreenShot(root);
Matrix rotateMatrix = new Matrix();
rotateMatrix.postRotate(Datas.rotationvalue);
Log.e("rotationvalue", Datas.rotationvalue+"...");
Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), rotateMatrix, false);
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
rotatedBitmap.compress(Bitmap.CompressFormat.PNG, 100, bytes);
try {
File f = new File(filepath);
if (!f.exists()) {
f.mkdir();
}
String folderpath = f.toString();
File file = new File(folderpath, filename + "." + filetype);
file.createNewFile();
FileOutputStream fo = new FileOutputStream(file);
fo.write(bytes.toByteArray());
fo.close();
Uri uri = Uri.fromFile(file);
Log.e("Edited img uri", uri.toString());
return uri;
} catch (Exception e) {
Log.e("Exception...occured", e.toString());
e.printStackTrace();
return null;
}
}
This code is working fine.At my own side, try at your side.
According to doc: last argument is filter boolean: true if the source
should be filtered. Only applies if the matrix contains more than just
translation.
Link for more info: Last argument more info
Save the image function is as follows:
private void saveBitmap(Bitmap bitmap, String fileName) {
File file = new File(Environment.getExternalStorageDirectory(), fileName);
FileOutputStream fileOS = null;
try {
fileOS = new FileOutputStream(file);
// quality: Hint to the compressor, 0-100. 0 meaning compress for small size, 100 meaning compress for max quality.
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOS);
fileOS.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fileOS != null) {
try {
fileOS.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Use the sample:
Bitmap bmp = BitmapFactory.decodeFile(filePathLocal);
Matrix matrix = new Matrix();
matrix.postRotate(getImageOrientation(filePathLocal));
rotatedBitmap = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);
saveBitmap(rotatedBitmap, "saved_rotated_image.jpg");
I'm trying to choose a photo using intents on Android. All works well and photos are being retrieved from any photos app (camera, gallery, screenshots etc.. even if selected from the new Photos app); except for the ones backed up online on Google Photos.
Photos taken in portrait will be retrieved in landscape when getting the Bitmap. I have code to get the orientation of the photo so I can translate accordingly, but the orientation is always 0 when choosing an online photo on the new Google Photos app. Any ideas on how I should get the orientation for these photos as 0 is being returned? Code below - thanks.
Starting intent
Intent i = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(i, IMPORT_PHOTO_RESULT);
Intent result
Uri selectedImageUri = data.getData();
imageBitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), selectedImageUri);
//fix rotation
int orientation = -1;
Cursor cursor = MediaStore.Images.Media.query(getContentResolver(), selectedImageUri, new String[] { MediaStore.Images.ImageColumns.ORIENTATION });
try {
if (cursor.moveToFirst()) {
orientation = cursor.getInt(0);
}
} finally {
cursor.close();
}
imageBitmap = Utils.rotateImageWithRotation(orientation, imageBitmap);
//get stream to display and send
ByteArrayOutputStream stream = new ByteArrayOutputStream();
imageBitmap.compress(Bitmap.CompressFormat.JPEG, 70, stream);
// get byte array here
byte[] bytearray = stream.toByteArray();
sendImage(bytearray, null);
rotate image
public static Bitmap rotateImageWithRotation(int rotationInDegrees, Bitmap mBitmap) {
Matrix matrix = new Matrix();
if (rotationInDegrees != 0f) {
matrix.preRotate(rotationInDegrees);
}
Bitmap adjustedBitmap = Bitmap.createBitmap(mBitmap, 0, 0, mBitmap.getWidth(), mBitmap.getHeight(), matrix, true);
return adjustedBitmap;
}
I gave up and used this amazing library instead. Kudos for the work!
https://github.com/coomar2841/image-chooser-library
You can try this:
Bitmap bitmap = null;
try {
Bitmap tmpBmp;
Uri uri = params[0]; // remove uri with uri from intent
int angle = 0;
Matrix m = new Matrix();
BitmapFactory.Options tempOption = new BitmapFactory.Options();
tempOption.inSampleSize = 2;
AssetFileDescriptor fileDescriptor = getContentResolver().openAssetFileDescriptor(uri, "r");
tmpBmp = BitmapFactory.decodeFileDescriptor(fileDescriptor.getFileDescriptor(), null, tempOption);
ExifInterface ei = new ExifInterface(uri.getPath());
int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
angle = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
angle = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
angle = 270;
break;
}
m.postRotate(angle);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;
if (Runtime.getRuntime().totalMemory() > 64 * 1024 * 1024) {
options.inPreferredConfig = Bitmap.Config.RGB_565;
}
bitmap = Bitmap.createBitmap(tmpBmp, 0, 0, tempOption.outWidth, tempOption.outHeight, m, true);
} catch (Exception e) {
Log.e(LOG_TAG, e.getMessage(), e);
}
return bitmap;
This question already has answers here:
Android saving file to external storage
(13 answers)
Closed 2 years ago.
I develop app that save images to sd Card and all the pictures are upside i want to rotate them and save them in the rotate position i choose .
i know how to rotate on my code but the image is not saved permanently.
here is my code :
//Rotate the picture
public static Bitmap rotate(Bitmap source, float angle) {
Matrix matrix = new Matrix();
matrix.postRotate(angle);
return Bitmap.createBitmap(source, 0, 0, source.getWidth(),source.getHeight(), matrix, false);
}
//Resize image
public void resizeImage(String path , int Wdist,int Hdist){
try
{
int inWidth = 0;
int inHeight = 0;
InputStream in = new FileInputStream(path);
// decode image size (decode metadata only, not the whole image)
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(in, null, options);
in.close();
in = null;
// save width and height
inWidth = options.outWidth;
inHeight = options.outHeight;
// decode full image pre-resized
in = new FileInputStream(path);
options = new BitmapFactory.Options();
// calc rought re-size (this is no exact resize)
options.inSampleSize = Math.max(inWidth/Wdist, inHeight/Hdist);
// decode full image
Bitmap roughBitmap = BitmapFactory.decodeStream(in, null, options);
// calc exact destination size
Matrix m = new Matrix();
RectF inRect = new RectF(0, 0, roughBitmap.getWidth(), roughBitmap.getHeight());
RectF outRect = new RectF(0, 0, Wdist, Hdist);
m.setRectToRect(inRect, outRect, Matrix.ScaleToFit.CENTER);
float[] values = new float[9];
m.getValues(values);
// resize bitmap
Bitmap resizedBitmap = Bitmap.createScaledBitmap(roughBitmap, (int) (roughBitmap.getWidth() * values[0]), (int) (roughBitmap.getHeight() * values[4]), true);
// save image
try
{
FileOutputStream out = new FileOutputStream(path);
resizedBitmap.compress(Bitmap.CompressFormat.JPEG, 80, out);
}
catch (Exception e)
{
Log.e("Image", e.getMessage(), e);
}
}
catch (IOException e)
{
Log.e("Image", e.getMessage(), e);
}
}
thanks for the helpers :)
You'll need to save the Bitmap back.
try {
File dir = new File("path/to/directory");
if(!dir.exists())
dir.mkdirs();
File file = new File(dir, "original_img_name.png");
FileOutputStream out;
out = new FileOutputStream(file);
bmp.compress(Bitmap.CompressFormat.PNG, 90, out);
} catch (Exception e) {
e.printStackTrace();
} finally {
try{
out.close();
} catch(Throwable ignore) {}
}
Edit 1 :
Replace
bmp.compress(Bitmap.CompressFormat.PNG, 90, out); with
resizedBitmap.compress(Bitmap.CompressFormat.JPEG, 80, out); and set correct values for the directory path and the image name. If you want to replace the previous images, use the original path and image name.
Also, make sure you include the following permission.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
You can also try this one
return Bitmap.createBitmap(source, 0, 0, source.getWidth(),source.getHeight(), matrix, true);
Go through this link
how to rotate a bitmap 90 degrees
The following code can help you compress and resize the bitmap.
Note:
Create a String type variable with name of photoPath and store the photo url in it.
public void compressImage(){
Log.i("compressPhoto", "Compress and resize photo started.");
// Getting Image
InputStream in = null;
try {
in = new FileInputStream(photoPath);
} catch (FileNotFoundException e) {
Log.e("TAG","originalFilePath is not valid", e);
}
BitmapFactory.Options options = new BitmapFactory.Options();
Bitmap bitmap = BitmapFactory.decodeStream(in, null, options);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap = bitmap.createScaledBitmap(bitmap,(int)(bitmap.getWidth()*0.2), (int)(bitmap.getHeight()*0.2), true);
bitmap.compress(Bitmap.CompressFormat.JPEG, 50, stream);
byte[] byteArray = stream.toByteArray();
// Storing Back
FileOutputStream outStream = null;
try {
outStream = new FileOutputStream(photoPath);
outStream.write(byteArray);
outStream.close();
} catch (Exception e) {
Log.e("TAG","could not save", e);
}
}
Android Saved Images into Gallery not Correctly Oriented
The value obtained after int getOrientationFromExif() is always the same: 1...
Don't know how to solve....
Please help me!
Can you help me to solve? The problem is inside
private PictureCallback mPicture = new PictureCallback()
{
#TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
#Override
public void onPictureTaken(byte[] data, Camera camera){
File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
try
{
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "MyCameraApp");
Bitmap myBitmap = BitmapFactory.decodeFile(pictureFile.getAbsolutePath());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
myBitmap = rotateImage(getOrientationFromExif(pictureFile), myBitmap);
myBitmap.compress(Bitmap.CompressFormat.JPEG, 70 /*ignored for PNG*/, bos);
byte[] bitmapdata = bos.toByteArray();
fos = new FileOutputStream(pictureFile);
fos.write(bitmapdata);
fos.close();
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED,
Uri.parse("file://"+ mediaStorageDir)));
}
catch(FileNotFoundException e)
{
Log.d(TAG, "File not found: "+e.getMessage());
}
catch(IOException e)
{
Log.d(TAG, "Error accessing file: "+e.getMessage());
}
}
};
public Bitmap rotateImage(int angle, Bitmap bitmapSrc)
{
Matrix matrix = new Matrix();
matrix.postRotate(angle);
return Bitmap.createBitmap(bitmapSrc, 0, 0,
bitmapSrc.getWidth(), bitmapSrc.getHeight(), matrix, true);
}
public int getOrientationFromExif(File imagePath)
{
int orientation = -1;
try
{
ExifInterface exif = new ExifInterface(imagePath.getAbsolutePath());
int exifOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
System.out.println("yuri"+exifOrientation);
switch (exifOrientation)
{
case ExifInterface.ORIENTATION_ROTATE_270:
orientation = 270;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
orientation = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_90:
orientation = 90;
break;
case ExifInterface.ORIENTATION_NORMAL:
orientation = 0;
break;
default:
break;
}
} catch (IOException e) {
Log.e(TAG, "Unable to get image exif orientation", e);
}
return orientation;
}
public static boolean isSdPresent() {
return android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);
}
private static File getOutputMediaFile(int type){
File mediaFile = null;
if(isSdPresent() == false)
{
Log.d(TAG, "There is no Sd card. Cannot use the camera");
}
else
{
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),".");
if(!mediaStorageDir.exists())
{
if(!mediaStorageDir.mkdirs())
{
Log.d("WorldCupApp", "failed to create directory");
return null;
}
}
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
if (type == MEDIA_TYPE_IMAGE)
{
mediaFile = new File(mediaStorageDir.getPath() + "IMG_"+ timeStamp + ".JPEG");
}
else
{
return null;
}
}
return mediaFile;
}
ExifInterface exif = new ExifInterface(imagePath.getAbsolutePath());
int exifOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
Problem is here always is 1 the orientation that means that doesn't need to rotate :(
When you fix your activity to landscape mode for a custom camera implementation the EXIF data will always have ORIENTATION_NORMAL for TAG_ORIENTATION. This is the same side effect that has activity.getWindowManager().getDefaultDisplay().getRotation() always returning ROTATION_90.
I fixed this by detecting the device rotation with an OrientationEventListener and then rewriting the EXIF orientation tag in my onPictureTaken callback to the proper value for the rotation.
Not sure if this behavior is device dependent, this is the behavior on a Galaxy S2 running 4.1.2.