diff options
Diffstat (limited to 'src/com/android/camera/data/RotationTask.java')
-rw-r--r-- | src/com/android/camera/data/RotationTask.java | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/src/com/android/camera/data/RotationTask.java b/src/com/android/camera/data/RotationTask.java new file mode 100644 index 000000000..8daead156 --- /dev/null +++ b/src/com/android/camera/data/RotationTask.java @@ -0,0 +1,161 @@ +/* + * 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 android.util.Log; + +import com.android.camera.data.LocalMediaData.PhotoData; +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 String TAG = "CAM_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.getOrientation(); + 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 { + 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) { + // Swap width and height after rotation. + int oldWidth = imageData.getWidth(); + int newWidth = imageData.getHeight(); + int newHeight = oldWidth; + values.put(Images.Media.WIDTH, newWidth); + values.put(Images.Media.HEIGHT, newHeight); + + // MediaStore using SQLite is thread safe. + values.put(Images.Media.ORIENTATION, finalRotationDegrees); + mContext.getContentResolver().update(imageData.getContentUri(), + values, "_id=?", + new String[] { + String.valueOf(imageData.getId()) }); + + double[] latLong = data.getLatLong(); + double latitude = 0; + double longitude = 0; + if (latLong != null) { + latitude = latLong[0]; + longitude = latLong[1]; + } + + result = new PhotoData(data.getId(), data.getTitle(), + data.getMimeType(), data.getDateTaken(), data.getDateModified(), + data.getPath(), newOrientation, newWidth, newHeight, + data.getSizeInBytes(), latitude, longitude); + } + + return result; + } + + @Override + protected void onPostExecute(LocalData result) { + mProgress.dismiss(); + if (result != null) { + mAdapter.updateData(mCurrentDataId, result); + } + } +} |