| /* |
| * Copyright (C) 2013 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.camera.data; |
| |
| import android.app.ProgressDialog; |
| import android.content.ContentValues; |
| import android.content.Context; |
| import android.os.AsyncTask; |
| import android.provider.MediaStore.Images; |
| |
| import com.android.camera.data.LocalMediaData.PhotoData; |
| import com.android.camera.debug.Log; |
| import com.android.camera.exif.ExifInterface; |
| import com.android.camera.exif.ExifTag; |
| import com.android.camera2.R; |
| |
| import java.io.File; |
| import java.io.FileNotFoundException; |
| import java.io.IOException; |
| |
| /** |
| * RotationTask can be used to rotate a {@link LocalData} by updating the exif |
| * data from jpeg file. Note that only {@link PhotoData} can be rotated. |
| */ |
| public class RotationTask extends AsyncTask<LocalData, Void, LocalData> { |
| private static final Log.Tag TAG = new Log.Tag("RotationTask"); |
| private final Context mContext; |
| private final LocalDataAdapter mAdapter; |
| private final int mCurrentDataId; |
| private final boolean mClockwise; |
| private ProgressDialog mProgress; |
| |
| public RotationTask(Context context, LocalDataAdapter adapter, |
| int currentDataId, boolean clockwise) { |
| mContext = context; |
| mAdapter = adapter; |
| mCurrentDataId = currentDataId; |
| mClockwise = clockwise; |
| } |
| |
| @Override |
| protected void onPreExecute() { |
| // Show a progress bar since the rotation could take long. |
| mProgress = new ProgressDialog(mContext); |
| int titleStringId = mClockwise ? R.string.rotate_right : R.string.rotate_left; |
| mProgress.setTitle(mContext.getString(titleStringId)); |
| mProgress.setMessage(mContext.getString(R.string.please_wait)); |
| mProgress.setCancelable(false); |
| mProgress.show(); |
| } |
| |
| @Override |
| protected LocalData doInBackground(LocalData... data) { |
| return rotateInJpegExif(data[0]); |
| } |
| |
| /** |
| * Rotates the image by updating the exif. Done in background thread. |
| * The worst case is the whole file needed to be re-written with |
| * modified exif data. |
| * |
| * @return A new {@link LocalData} object which containing the new info. |
| */ |
| private LocalData rotateInJpegExif(LocalData data) { |
| if (!(data instanceof PhotoData)) { |
| Log.w(TAG, "Rotation can only happen on PhotoData."); |
| return null; |
| } |
| |
| PhotoData imageData = (PhotoData) data; |
| int originRotation = imageData.getRotation(); |
| int finalRotationDegrees; |
| if (mClockwise) { |
| finalRotationDegrees = (originRotation + 90) % 360; |
| } else { |
| finalRotationDegrees = (originRotation + 270) % 360; |
| } |
| |
| String filePath = imageData.getPath(); |
| ContentValues values = new ContentValues(); |
| boolean success = false; |
| int newOrientation = 0; |
| if (imageData.getMimeType().equalsIgnoreCase(LocalData.MIME_TYPE_JPEG)) { |
| ExifInterface exifInterface = new ExifInterface(); |
| ExifTag tag = exifInterface.buildTag( |
| ExifInterface.TAG_ORIENTATION, |
| ExifInterface.getOrientationValueForRotation( |
| finalRotationDegrees)); |
| if (tag != null) { |
| exifInterface.setTag(tag); |
| try { |
| // Note: This only works if the file already has some EXIF. |
| exifInterface.forceRewriteExif(filePath); |
| long fileSize = new File(filePath).length(); |
| values.put(Images.Media.SIZE, fileSize); |
| newOrientation = finalRotationDegrees; |
| success = true; |
| } catch (FileNotFoundException e) { |
| Log.w(TAG, "Cannot find file to set exif: " + filePath); |
| } catch (IOException e) { |
| Log.w(TAG, "Cannot set exif data: " + filePath); |
| } |
| } else { |
| Log.w(TAG, "Cannot build tag: " + ExifInterface.TAG_ORIENTATION); |
| } |
| } |
| |
| PhotoData result = null; |
| if (success) { |
| // MediaStore using SQLite is thread safe. |
| values.put(Images.Media.ORIENTATION, finalRotationDegrees); |
| mContext.getContentResolver().update(imageData.getUri(), |
| values, null, null); |
| double[] latLong = data.getLatLong(); |
| double latitude = 0; |
| double longitude = 0; |
| if (latLong != null) { |
| latitude = latLong[0]; |
| longitude = latLong[1]; |
| } |
| |
| result = new PhotoData(data.getContentId(), data.getTitle(), |
| data.getMimeType(), data.getDateTaken(), data.getDateModified(), |
| data.getPath(), newOrientation, imageData.getWidth(), |
| imageData.getHeight(), data.getSizeInBytes(), latitude, longitude); |
| } |
| |
| return result; |
| } |
| |
| @Override |
| protected void onPostExecute(LocalData result) { |
| mProgress.dismiss(); |
| if (result != null) { |
| mAdapter.updateData(mCurrentDataId, result); |
| } |
| } |
| } |