Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android EXIF data always 0, how to change it?

I have an app that captures photos using the native Camera and then uploads them to a server. My problem is that all the photos have an EXIF orientation value of 0, and this messes up the display elsewhere.

How can I change the EXIF orientation? I'm not looking for a way to correct it for every circumstance, just change it to a different value.

I'm using a Samsung Galaxy Note 4

I tried this solution that sets the camera orientation before taking photos: Setting Android Photo EXIF Orientation

Camera c = Camera.open(); c.setDisplayOrientation(90);  Camera.Parameters params = mCamera.getParameters(); params.setRotation(0); // tried 0, 90, 180 c.setParameters(params); 

but it doesn't influence the resulting EXIF data, its still always 0

I also tried these solutions where the image is rotated after it is taken: EXIF orientation tag value always 0 for image taken with portrait camera app android

and while this rotates the photo, the EXIF orientation is still always 0.

I also tried setting the EXIF data directly: How to save Exif data after bitmap compression in Android

private Camera.PictureCallback mPicture = new Camera.PictureCallback() {     @Override     public void onPictureTaken(byte[] data, Camera camera) {         final File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE, "");         try {             FileOutputStream fos = new FileOutputStream(pictureFile);              ExifInterface exif = new ExifInterface(pictureFile.toString());             exif.setAttribute(ExifInterface.TAG_ORIENTATION, "3");             exif.saveAttributes();              fos.write(data);             fos.close();              //upload photo..         }     } } 

but EXIF Orientation is still 0 after uploading.

I have also looked at these solutions:

Exif data TAG_ORIENTATION always 0

How to write exif data to image in Android?

How to get the Correct orientation of the image selected from the Default Image gallery

how to set camera Image orientation?

but they all involve correcting the orientation by rotating, which doesn't influence the EXIF data, or setting the EXIF data directly which doesn't seem to work.

How can I change the file's EXIF orientation data from 0 to 3?

UPDATE:

here is my upload code:

Bitmap sBitmap = null; final File sResizedFile = getOutputMediaFile(MEDIA_TYPE_IMAGE, "_2"); try {     sBitmap = BitmapFactory.decodeStream(new FileInputStream(pictureFile), null, options); } catch (FileNotFoundException e) {     Log.e("App", "[MainActivity] unable to convert pictureFile to bitmap");     e.printStackTrace();     return; }  // ... compute sw and sh int values  Bitmap sOut = Bitmap.createScaledBitmap(sBitmap, sw, sh, false); Bitmap rotatedBitmap = rotateBitmap(sOut, 3); FileOutputStream sfOut; try {     sfOut = new FileOutputStream(sResizedFile);     rotatedBitmap.compress(Bitmap.CompressFormat.JPEG, 70, sfOut);     sfOut.flush();     sfOut.close();     sBitmap.recycle();     sOut.recycle();     rotatedBitmap.recycle(); } catch (Exception e) {     Log.e("App", "[MainActivity] unable to save thumbnail");     e.printStackTrace();     return; } // upload small thumbnail TransferObserver sObserver = transferUtility.upload(             "stills/small",        /* The bucket to upload to */             filename + ".jpg",     /* The key for the uploaded object */             sResizedFile           /* The file where the data to upload exists */ ); 
like image 813
Cbas Avatar asked Sep 08 '16 21:09

Cbas


People also ask

Can you modify EXIF data?

Select the picture you want to edit EXIF data for. To view EXIF data, you can tap the various icons below the image. To edit or remove EXIF data (after you pay for the app), tap Metadata. Now select Remove or Edit.

How do I fix EXIF files?

Just right click any image file, choose Properties and click the Details tab. You can now edit a wide range of metadata associated with that image from the camera model to the shooting date to copyright information and more.

How do I get rid of EXIF data on Android?

If removing EXIF data is what you're after, tap the “ Exif ” button beside the eyeball. The “Remove EXIF” screen is pretty straightforward to use. Just tap the checkbox next to the data you'd like to remove. If you want to remove it all, just hit the very first check box at the top, which will select everything.


2 Answers

As you can see, the The EXIF information is not reliable on Android (especially Samsung devices).

However the phone SQL database holding the references to Media object is reliable. I would propose going this way.

Getting the orientation from the Uri:

private static int getOrientation(Context context, Uri photoUri) {     Cursor cursor = context.getContentResolver().query(photoUri,             new String[]{MediaStore.Images.ImageColumns.ORIENTATION}, null, null, null);      if (cursor.getCount() != 1) {         cursor.close();         return -1;     }      cursor.moveToFirst();     int orientation = cursor.getInt(0);     cursor.close();     cursor = null;     return orientation; } 

Then initialize rotated Bitmap:

public static Bitmap rotateBitmap(Context context, Uri photoUri, Bitmap bitmap) {     int orientation = getOrientation(context, photoUri);     if (orientation <= 0) {         return bitmap;     }     Matrix matrix = new Matrix();     matrix.postRotate(orientation);     bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false);     return bitmap; } 

If you want to change the orientation of the image, try the following snippet:

public static boolean setOrientation(Context context, Uri fileUri, int orientation) {     ContentValues values = new ContentValues();     values.put(MediaStore.Images.Media.ORIENTATION, orientation);     int rowsUpdated = context.getContentResolver().update(fileUri, values, null, null);     return rowsUpdated > 0; } 

If you set the orientation of the image, later it will be constantly set at the correct orientation. There is need to make use of ExifInterface later, because the image is already rotated in proper way.

If this method is not satisfactory, then you could try this method

like image 66
R. Zagórski Avatar answered Sep 17 '22 17:09

R. Zagórski


You have accepted your own answer as solution. My rant is just useful side-info, anyways...

The "However..." in your Answer suggests while you now know the cause, you don't have a fix.

Turns out my code was able to set the EXIF data, but there is a discrepancy between how Android interprets this data and how iOS... interprets it.

This could be an endianness issue. You can try manually changing the endianness setting of Exif by opening your jpeg in a hex editor and finding...

  • The bytes 45 78 69 66 (makes "Exif" text) followed by two zero bytes 00 00.
  • Then it should be 49 49 (makes "II" text) which means read data as little endian format.
  • If you replace it with 4D 4D (or "MM" text) then the reading side will consider data as big endian.

Test this in iOS to see if numbers are now correct.

and regarding this...

However, setting 3 shows up as0 on iOS and the image is sideways in Chrome.
Setting 6 shows up as 3 on iOS and the image looks right in Chrome.

Only thing I can add is that iOS Mac is Big Endian* and Android/PC is Little Endian. Essentially Little Endian reads/writes bytes as right-to-left whilst Big Endian is opposite.

In binary : 011 means 3 and 110 means 6. The difference between 3 and 6 is simply the reading order of those bits of ones & zeroes. So a system that reads as zero-one-one gets a result of 3 but the other Endian system will read a byte with same bits as one-one-zero and tell you result is a 6. I can't explain why "3 shows up as 0" without a test file to analyse bytes but it's a strange result to me.

</end rant>
<sleep>

*note: While Macs are Big Endian, double-checking says iOS uses Little Endian system after all. Your numbers still suggest a Big vs Little Endian issue though.

like image 45
VC.One Avatar answered Sep 18 '22 17:09

VC.One