Hi,
I hope reader knows exif information. In this post I’ll show you how to maintain exif information when you re-size image.
Android has ExifInterface to read exif information of image file. It is from API level 5.
Jul 16, 2011 |
Do not use String constant, because more new tags are introduced in newer version of SDK. Since Android is forward compatible, it’s good practice to use all tag as string. If tag is supported then it’ll copy other wise not.
Tag and more information about ExifInterface is here.
main.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent"> <ImageView android:id="@+id/ImageView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" /> <Button android:layout_width="wrap_content" android:id="@+id/LoadButton" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:text="Load" /> <Button android:layout_width="wrap_content" android:id="@+id/ResizeButton" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:text="Resize and save" /> </RelativeLayout>
AndroidResizeImageActivity.java
package com.isummation.imageresizer; import java.io.File; import java.io.FileOutputStream; import android.app.Activity; import android.content.Intent; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.media.ExifInterface; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.provider.MediaStore; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ImageView; import android.widget.Toast; public class AndroidResizeImageActivity extends Activity { private static final int PICK_IMAGE = 1; private Button ResizeBtn; private Button LoadBtn; private Bitmap bitmap; private ImageView imgView; private static int newWidth = 200; private static int newHeight = 200; private String filePath; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); imgView = (ImageView) findViewById(R.id.ImageView); LoadBtn = (Button) findViewById(R.id.LoadButton); ResizeBtn = (Button) findViewById(R.id.ResizeButton); LoadBtn.setOnClickListener(new OnClickListener() { public void onClick(View v) { // TODO Auto-generated method stub try { Intent intent = new Intent(); intent.setType("image/*"); intent.setAction(Intent.ACTION_GET_CONTENT); startActivityForResult( Intent.createChooser(intent, "Select image"), PICK_IMAGE); } catch (Exception e) { Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show(); Log.e(e.getClass().getName(), e.getMessage(), e); } } }); ResizeBtn.setOnClickListener(new OnClickListener() { public void onClick(View v) { // TODO Auto-generated method stub try { int width = bitmap.getWidth(); int height = bitmap.getHeight(); float scaleWidth = ((float) newWidth) / width; float scaleHeight = ((float) newHeight) / height; Matrix matrix = new Matrix(); matrix.postScale(scaleWidth, scaleHeight); Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, false); // Save new image String path = Environment.getExternalStorageDirectory() .toString(); File file = new File(path, "NewImage.jpeg"); FileOutputStream fos = new FileOutputStream(file); resizedBitmap.compress(CompressFormat.JPEG, 100, fos); // copy paste exif information from original file to new // file ExifInterface oldexif = new ExifInterface(filePath); ExifInterface newexif = new ExifInterface(file.getAbsolutePath()); int build = Build.VERSION.SDK_INT; // From API 11 if (build >= 11) { if (oldexif.getAttribute("FNumber") != null) { newexif.setAttribute("FNumber", oldexif.getAttribute("FNumber")); } if (oldexif.getAttribute("ExposureTime") != null) { newexif.setAttribute("ExposureTime", oldexif.getAttribute("ExposureTime")); } if (oldexif.getAttribute("ISOSpeedRatings") != null) { newexif.setAttribute("ISOSpeedRatings", oldexif.getAttribute("ISOSpeedRatings")); } } // From API 9 if (build >= 9) { if (oldexif.getAttribute("GPSAltitude") != null) { newexif.setAttribute("GPSAltitude", oldexif.getAttribute("GPSAltitude")); } if (oldexif.getAttribute("GPSAltitudeRef") != null) { newexif.setAttribute("GPSAltitudeRef", oldexif.getAttribute("GPSAltitudeRef")); } } // From API 8 if (build >= 8) { if (oldexif.getAttribute("FocalLength") != null) { newexif.setAttribute("FocalLength", oldexif.getAttribute("FocalLength")); } if (oldexif.getAttribute("GPSDateStamp") != null) { newexif.setAttribute("GPSDateStamp", oldexif.getAttribute("GPSDateStamp")); } if (oldexif.getAttribute("GPSProcessingMethod") != null) { newexif.setAttribute( "GPSProcessingMethod", oldexif.getAttribute("GPSProcessingMethod")); } if (oldexif.getAttribute("GPSTimeStamp") != null) { newexif.setAttribute("GPSTimeStamp", "" + oldexif.getAttribute("GPSTimeStamp")); } } if (oldexif.getAttribute("DateTime") != null) { newexif.setAttribute("DateTime", oldexif.getAttribute("DateTime")); } if (oldexif.getAttribute("Flash") != null) { newexif.setAttribute("Flash", oldexif.getAttribute("Flash")); } if (oldexif.getAttribute("GPSLatitude") != null) { newexif.setAttribute("GPSLatitude", oldexif.getAttribute("GPSLatitude")); } if (oldexif.getAttribute("GPSLatitudeRef") != null) { newexif.setAttribute("GPSLatitudeRef", oldexif.getAttribute("GPSLatitudeRef")); } if (oldexif.getAttribute("GPSLongitude") != null) { newexif.setAttribute("GPSLongitude", oldexif.getAttribute("GPSLongitude")); } if (oldexif.getAttribute("GPSLatitudeRef") != null) { newexif.setAttribute("GPSLongitudeRef", oldexif.getAttribute("GPSLongitudeRef")); } //Need to update it, with your new height width newexif.setAttribute("ImageLength", "200"); newexif.setAttribute("ImageWidth", "200"); if (oldexif.getAttribute("Make") != null) { newexif.setAttribute("Make", oldexif.getAttribute("Make")); } if (oldexif.getAttribute("Model") != null) { newexif.setAttribute("Model", oldexif.getAttribute("Model")); } if (oldexif.getAttribute("Orientation") != null) { newexif.setAttribute("Orientation", oldexif.getAttribute("Orientation")); } if (oldexif.getAttribute("WhiteBalance") != null) { newexif.setAttribute("WhiteBalance", oldexif.getAttribute("WhiteBalance")); } newexif.saveAttributes(); // MediaStore.Images.Media.insertImage(getContentResolver(),file.getAbsolutePath(),file.getName(),file.getName()); Toast.makeText(getApplicationContext(), "Image resized & saved successfully", Toast.LENGTH_SHORT).show(); } catch (Exception e) { Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show(); Log.e(e.getClass().getName(), e.getMessage(), e); } } }); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case PICK_IMAGE: if (resultCode == Activity.RESULT_OK) { Uri selectedImageUri = data.getData(); try { // OI FILE Manager String filemanagerstring = selectedImageUri.getPath(); // MEDIA GALLERY String selectedImagePath = getPath(selectedImageUri); if (selectedImagePath != null) { filePath = selectedImagePath; } else if (filemanagerstring != null) { filePath = filemanagerstring; } else { Toast.makeText(getApplicationContext(), "Unknown path", Toast.LENGTH_LONG).show(); Log.e("Bitmap", "Unknown path"); } if (filePath != null) { decodeFile(); } else { bitmap = null; } } catch (Exception e) { Toast.makeText(getApplicationContext(), "Internal error", Toast.LENGTH_LONG).show(); Log.e(e.getClass().getName(), e.getMessage(), e); } } break; default: } } public String getPath(Uri uri) { String[] projection = { MediaStore.Images.Media.DATA }; Cursor cursor = managedQuery(uri, projection, null, null, null); if (cursor != null) { // HERE YOU WILL GET A NULLPOINTER IF CURSOR IS NULL // THIS CAN BE, IF YOU USED OI FILE MANAGER FOR PICKING THE MEDIA int column_index = cursor .getColumnIndexOrThrow(MediaStore.Images.Media.DATA); cursor.moveToFirst(); return cursor.getString(column_index); } else return null; } public void decodeFile() { /* * Intentionally commented this code. To get original image size. It may * require if image is of very high resolution. * * // 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 = 1; * while (true) { if (width_tmp < REQUIRED_SIZE && height_tmp < * REQUIRED_SIZE) break; width_tmp /= 2; height_tmp /= 2; scale *= 2; } * * // Decode with inSampleSize BitmapFactory.Options o2 = new * BitmapFactory.Options(); o2.inSampleSize = scale; bitmap = * BitmapFactory.decodeFile(filePath, o2); */ bitmap = BitmapFactory.decodeFile(filePath); imgView.setImageBitmap(bitmap); } }
To check exif information online, this would be best.
Download full source code
Project is compiled with SDK 2.3 but it is compatible to SDK 2.1.
Update: Updated code to fix exif information errors.
Updated code, and solved NullPointerExceptions
Thanks Vikas you are really doing great job by sharing these info.
please keep it up.
Hello!!
In the row 161 there is an error?
if (oldexif.getAttribute(“GPSLatitudeRef”) != null)
{
newexif.setAttribute(“GPSLongitudeRef”,oldexif.getAttribute(“GPSLongitudeRef”));
}
NO “getAttribute(GPSLatitudeRef)”–> YES “getAttribute(GPSLongitudeRef)”
bye bye
Thanks for the review.
thank you very much!
I have tried your code,exif details not copied to new image.It is not working.Can you help me to make it workable for me.I didn’t get any error.I got the output image with no Exif details.
your link source code broken, please you upload again, thanks.