10

Is there a way to resize a JPEG image file (from filesystem to filesystem) without removing meta data (just like ImageMagicks convert in.jpg -resize 50% out.jpg)?

The only way I found to resize .jpg files I found is BitmapFactory.decodeStream and Bitmap.compress, which looks like a lot of overhead if I manually need to transfer image meta data.

Simon Warta
  • 10,850
  • 5
  • 40
  • 78
  • By resize, do you mean resampling the image to change its resolution? If so, AFAIK, the only built-in stuff for that is what you cite in your question. – CommonsWare Nov 21 '16 at 20:55
  • Yes, change the resolution. I just added a sample command to illustrate what I am searching for. – Simon Warta Nov 21 '16 at 20:58
  • Unless there's something lurking in the SDK for this that I have missed, your options will be to use a third-party library or [handle the EXIF headers yourself](https://commonsware.com/blog/2016/05/31/tale-two-exifinterfaces.html) in conjunction with `BitmapFactory`/`Bitmap`. – CommonsWare Nov 21 '16 at 21:03
  • Have you tried ImageMagick for android given here : https://github.com/paulasiimwe/Android-ImageMagick, I think this should solve your problem. – Abhinav Puri Nov 27 '16 at 09:28
  • @AbhinavPuri beautiful idea, thanks. I'll have a look at it. Feel free to convert your comment into an answer. – Simon Warta Nov 27 '16 at 13:59
  • @SimonWarta Okay, I have posted it as answer. – Abhinav Puri Nov 28 '16 at 07:43

1 Answers1

3

It may be possible to read the metadata with android.media.ExifInterface, compress the image via Bitmap.compress and then save the metadata back:

String filename = "yourfile.jpg";
// this reads all meta data
ExifInterface exif = new ExifInterface(filename);

// read and compress file
Bitmap bitmap = BitmapFactory.decodeFile(filename);
FileOutputStream fos = new FileOutputStream(filename);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos);
fos.close();

// write meta data back
exif.saveAttributes();

I didn't test it, but looking at the source code of ExifInterface, it may work. If you don't want to rely on the implementation details, you could of course loop through all attributes and copy them.


Another solution would be to use the Android Exif Extended library. It is a small project to read and write exif data.
Manuel Allenspach
  • 12,467
  • 14
  • 54
  • 76
  • The question is what "the original image file" from the saveAttributes() means. This might be and open file handle or something. I guess the way to use this properly is to have two ExifInterface instances and copy everything from one to the other. – Simon Warta Nov 29 '16 at 14:55
  • @SimonWarta If you look at [the source code](http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.1.1_r1/android/media/ExifInterface.java#ExifInterface.saveAttributes%28%29), it doesn't have an open file handle (as far as I can tell). It calls a native method with the file name and the attributes as parameters. – Manuel Allenspach Nov 29 '16 at 15:39
  • That might work for one Android version. The issue is that you are abusing detail of the specific implementation. saveAttributes is documented to save the changed attributes of the original file, not save the new ones to a new file. One day the implementation might only write changes to disk, not all attributes. Look e.g. into the two new API24 constructors. Those will enforce a different implementation. Anyways, you can adapt the answer to a loop-and-copy version with two ExifInterface objects. – Simon Warta Nov 29 '16 at 18:07