diff options
author | Michael Jurka <mikejurka@google.com> | 2013-10-10 21:28:40 -0700 |
---|---|---|
committer | Michael Jurka <mikejurka@google.com> | 2013-10-12 01:12:36 -0700 |
commit | 8713a94562c535bd2cc7d72e767caf9468d7bbaa (patch) | |
tree | 2c8260ed8a7d7e1fa53c1567b17fa14eb0346f09 /src | |
parent | 982470ead562f5cb99e9bf5a26610473737b4a5f (diff) | |
download | android_packages_apps_Trebuchet-8713a94562c535bd2cc7d72e767caf9468d7bbaa.tar.gz android_packages_apps_Trebuchet-8713a94562c535bd2cc7d72e767caf9468d7bbaa.tar.bz2 android_packages_apps_Trebuchet-8713a94562c535bd2cc7d72e767caf9468d7bbaa.zip |
Add EXIF rotation support to wallpaper picker
Bug: 11137824
Change-Id: I64e488207ffea219fca5ee00f47b98ccb2ac86d8
Diffstat (limited to 'src')
-rw-r--r-- | src/com/android/launcher3/CropView.java | 105 | ||||
-rw-r--r-- | src/com/android/launcher3/SavedWallpaperImages.java | 4 | ||||
-rw-r--r-- | src/com/android/launcher3/WallpaperCropActivity.java | 174 | ||||
-rw-r--r-- | src/com/android/launcher3/WallpaperPickerActivity.java | 50 | ||||
-rw-r--r-- | src/com/android/photos/views/TiledImageView.java | 2 |
5 files changed, 262 insertions, 73 deletions
diff --git a/src/com/android/launcher3/CropView.java b/src/com/android/launcher3/CropView.java index c8b974d01..9224e3bb2 100644 --- a/src/com/android/launcher3/CropView.java +++ b/src/com/android/launcher3/CropView.java @@ -17,9 +17,11 @@ package com.android.launcher3; import android.content.Context; +import android.graphics.Matrix; import android.graphics.Point; import android.graphics.RectF; import android.util.AttributeSet; +import android.util.FloatMath; import android.view.MotionEvent; import android.view.ScaleGestureDetector; import android.view.ScaleGestureDetector.OnScaleGestureListener; @@ -36,10 +38,18 @@ public class CropView extends TiledImageView implements OnScaleGestureListener { private long mTouchDownTime; private float mFirstX, mFirstY; private float mLastX, mLastY; + private float mCenterX, mCenterY; private float mMinScale; private boolean mTouchEnabled = true; private RectF mTempEdges = new RectF(); + private float[] mTempPoint = new float[] { 0, 0 }; + private float[] mTempCoef = new float[] { 0, 0 }; + private float[] mTempAdjustment = new float[] { 0, 0 }; + private float[] mTempImageDims = new float[] { 0, 0 }; + private float[] mTempRendererCenter = new float[] { 0, 0 }; TouchCallback mTouchCallback; + Matrix mRotateMatrix; + Matrix mInverseRotateMatrix; public interface TouchCallback { void onTouchDown(); @@ -54,17 +64,43 @@ public class CropView extends TiledImageView implements OnScaleGestureListener { public CropView(Context context, AttributeSet attrs) { super(context, attrs); mScaleGestureDetector = new ScaleGestureDetector(context, this); + mRotateMatrix = new Matrix(); + mInverseRotateMatrix = new Matrix(); + } + + private float[] getImageDims() { + final float imageWidth = mRenderer.source.getImageWidth(); + final float imageHeight = mRenderer.source.getImageHeight(); + float[] imageDims = mTempImageDims; + imageDims[0] = imageWidth; + imageDims[1] = imageHeight; + mRotateMatrix.mapPoints(imageDims); + imageDims[0] = Math.abs(imageDims[0]); + imageDims[1] = Math.abs(imageDims[1]); + return imageDims; } private void getEdgesHelper(RectF edgesOut) { final float width = getWidth(); final float height = getHeight(); - final float imageWidth = mRenderer.source.getImageWidth(); - final float imageHeight = mRenderer.source.getImageHeight(); + final float[] imageDims = getImageDims(); + final float imageWidth = imageDims[0]; + final float imageHeight = imageDims[1]; + + float initialCenterX = mRenderer.source.getImageWidth() / 2f; + float initialCenterY = mRenderer.source.getImageHeight() / 2f; + + float[] rendererCenter = mTempRendererCenter; + rendererCenter[0] = mCenterX - initialCenterX; + rendererCenter[1] = mCenterY - initialCenterY; + mRotateMatrix.mapPoints(rendererCenter); + rendererCenter[0] += imageWidth / 2; + rendererCenter[1] += imageHeight / 2; + final float scale = mRenderer.scale; - float centerX = (width / 2f - mRenderer.centerX + (imageWidth - width) / 2f) + float centerX = (width / 2f - rendererCenter[0] + (imageWidth - width) / 2f) * scale + width / 2f; - float centerY = (height / 2f - mRenderer.centerY + (imageHeight - height) / 2f) + float centerY = (height / 2f - rendererCenter[1] + (imageHeight - height) / 2f) * scale + height / 2f; float leftEdge = centerX - imageWidth / 2f * scale; float rightEdge = centerX + imageWidth / 2f * scale; @@ -77,6 +113,10 @@ public class CropView extends TiledImageView implements OnScaleGestureListener { edgesOut.bottom = bottomEdge; } + public int getImageRotation() { + return mRenderer.rotation; + } + public RectF getCrop() { final RectF edges = mTempEdges; getEdgesHelper(edges); @@ -96,6 +136,12 @@ public class CropView extends TiledImageView implements OnScaleGestureListener { public void setTileSource(TileSource source, Runnable isReadyCallback) { super.setTileSource(source, isReadyCallback); + mCenterX = mRenderer.centerX; + mCenterY = mRenderer.centerY; + mRotateMatrix.reset(); + mRotateMatrix.setRotate(mRenderer.rotation); + mInverseRotateMatrix.reset(); + mInverseRotateMatrix.setRotate(-mRenderer.rotation); updateMinScale(getWidth(), getHeight(), source, true); } @@ -115,8 +161,10 @@ public class CropView extends TiledImageView implements OnScaleGestureListener { mRenderer.scale = 1; } if (source != null) { - mMinScale = Math.max(w / (float) source.getImageWidth(), - h / (float) source.getImageHeight()); + final float[] imageDims = getImageDims(); + final float imageWidth = imageDims[0]; + final float imageHeight = imageDims[1]; + mMinScale = Math.max(w / imageWidth, h / imageHeight); mRenderer.scale = Math.max(mMinScale, mRenderer.scale); } } @@ -154,7 +202,13 @@ public class CropView extends TiledImageView implements OnScaleGestureListener { final RectF edges = mTempEdges; getEdgesHelper(edges); final float scale = mRenderer.scale; - mRenderer.centerX += Math.ceil(edges.left / scale); + mCenterX += Math.ceil(edges.left / scale); + updateCenter(); + } + + private void updateCenter() { + mRenderer.centerX = Math.round(mCenterX); + mRenderer.centerY = Math.round(mCenterY); } public void setTouchEnabled(boolean enabled) { @@ -215,8 +269,13 @@ public class CropView extends TiledImageView implements OnScaleGestureListener { mScaleGestureDetector.onTouchEvent(event); switch (action) { case MotionEvent.ACTION_MOVE: - mRenderer.centerX += (mLastX - x) / mRenderer.scale; - mRenderer.centerY += (mLastY - y) / mRenderer.scale; + float[] point = mTempPoint; + point[0] = (mLastX - x) / mRenderer.scale; + point[1] = (mLastY - y) / mRenderer.scale; + mInverseRotateMatrix.mapPoints(point); + mCenterX += point[0]; + mCenterY += point[1]; + updateCenter(); invalidate(); break; } @@ -226,18 +285,32 @@ public class CropView extends TiledImageView implements OnScaleGestureListener { final RectF edges = mTempEdges; getEdgesHelper(edges); final float scale = mRenderer.scale; + + float[] coef = mTempCoef; + coef[0] = 1; + coef[1] = 1; + mRotateMatrix.mapPoints(coef); + float[] adjustment = mTempAdjustment; + mTempAdjustment[0] = 0; + mTempAdjustment[1] = 0; if (edges.left > 0) { - mRenderer.centerX += Math.ceil(edges.left / scale); - } - if (edges.right < getWidth()) { - mRenderer.centerX += (edges.right - getWidth()) / scale; + adjustment[0] = edges.left / scale; + } else if (edges.right < getWidth()) { + adjustment[0] = (edges.right - getWidth()) / scale; } if (edges.top > 0) { - mRenderer.centerY += Math.ceil(edges.top / scale); + adjustment[1] = FloatMath.ceil(edges.top / scale); + } else if (edges.bottom < getHeight()) { + adjustment[1] = (edges.bottom - getHeight()) / scale; } - if (edges.bottom < getHeight()) { - mRenderer.centerY += (edges.bottom - getHeight()) / scale; + for (int dim = 0; dim <= 1; dim++) { + if (coef[dim] > 0) adjustment[dim] = FloatMath.ceil(adjustment[dim]); } + + mInverseRotateMatrix.mapPoints(adjustment); + mCenterX += adjustment[0]; + mCenterY += adjustment[1]; + updateCenter(); } } diff --git a/src/com/android/launcher3/SavedWallpaperImages.java b/src/com/android/launcher3/SavedWallpaperImages.java index ee4888d2b..8d5b00535 100644 --- a/src/com/android/launcher3/SavedWallpaperImages.java +++ b/src/com/android/launcher3/SavedWallpaperImages.java @@ -61,7 +61,9 @@ public class SavedWallpaperImages extends BaseAdapter implements ListAdapter { String imageFilename = a.getSavedImages().getImageFilename(mDbId); File file = new File(a.getFilesDir(), imageFilename); CropView v = a.getCropView(); - v.setTileSource(new BitmapRegionTileSource(a, file.getAbsolutePath(), 1024, 0), null); + int rotation = WallpaperCropActivity.getRotationFromExif(file.getAbsolutePath()); + v.setTileSource( + new BitmapRegionTileSource(a, file.getAbsolutePath(), 1024, rotation), null); v.moveToLeft(); v.setTouchEnabled(false); } diff --git a/src/com/android/launcher3/WallpaperCropActivity.java b/src/com/android/launcher3/WallpaperCropActivity.java index fe09a552c..79cc88ef9 100644 --- a/src/com/android/launcher3/WallpaperCropActivity.java +++ b/src/com/android/launcher3/WallpaperCropActivity.java @@ -37,12 +37,14 @@ import android.graphics.RectF; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; +import android.util.FloatMath; import android.util.Log; import android.view.Display; import android.view.View; import android.view.WindowManager; import com.android.gallery3d.common.Utils; +import com.android.gallery3d.exif.ExifInterface; import com.android.photos.BitmapRegionTileSource; import java.io.BufferedInputStream; @@ -88,7 +90,8 @@ public class WallpaperCropActivity extends Activity { Intent cropIntent = this.getIntent(); final Uri imageUri = cropIntent.getData(); - mCropView.setTileSource(new BitmapRegionTileSource(this, imageUri, 1024, 0), null); + int rotation = getRotationFromExif(this, imageUri); + mCropView.setTileSource(new BitmapRegionTileSource(this, imageUri, 1024, rotation), null); mCropView.setTouchEnabled(true); // Action bar // Show the custom action bar view @@ -168,9 +171,47 @@ public class WallpaperCropActivity extends Activity { return new Point(defaultWidth, defaultHeight); } + public static int getRotationFromExif(String path) { + return getRotationFromExifHelper(path, null, 0, null, null); + } + + public static int getRotationFromExif(Context context, Uri uri) { + return getRotationFromExifHelper(null, null, 0, context, uri); + } + + public static int getRotationFromExif(Resources res, int resId) { + return getRotationFromExifHelper(null, res, resId, null, null); + } + + private static int getRotationFromExifHelper( + String path, Resources res, int resId, Context context, Uri uri) { + ExifInterface ei = new ExifInterface(); + try { + if (path != null) { + ei.readExif(path); + } else if (uri != null) { + InputStream is = context.getContentResolver().openInputStream(uri); + BufferedInputStream bis = new BufferedInputStream(is); + ei.readExif(bis); + } else { + InputStream is = res.openRawResource(resId); + BufferedInputStream bis = new BufferedInputStream(is); + ei.readExif(bis); + } + Integer ori = ei.getTagIntValue(ExifInterface.TAG_ORIENTATION); + if (ori != null) { + return ExifInterface.getRotationForOrientationValue(ori.shortValue()); + } + } catch (IOException e) { + Log.w(LOGTAG, "Getting exif data failed", e); + } + return 0; + } + protected void setWallpaper(String filePath, final boolean finishActivityWhenDone) { - BitmapCropTask cropTask = new BitmapCropTask(this, - filePath, null, 0, 0, true, false, null); + int rotation = getRotationFromExif(filePath); + BitmapCropTask cropTask = new BitmapCropTask( + this, filePath, null, rotation, 0, 0, true, false, null); final Point bounds = cropTask.getImageBounds(); Runnable onEndCrop = new Runnable() { public void run() { @@ -190,6 +231,7 @@ public class WallpaperCropActivity extends Activity { Resources res, int resId, final boolean finishActivityWhenDone) { // crop this image and scale it down to the default wallpaper size for // this device + int rotation = getRotationFromExif(res, resId); Point inSize = mCropView.getSourceDimensions(); Point outSize = getDefaultWallpaperSize(getResources(), getWindowManager()); @@ -207,8 +249,7 @@ public class WallpaperCropActivity extends Activity { } }; BitmapCropTask cropTask = new BitmapCropTask(this, res, resId, - crop, outSize.x, outSize.y, - true, false, onEndCrop); + crop, rotation, outSize.x, outSize.y, true, false, onEndCrop); cropTask.execute(); } @@ -220,8 +261,6 @@ public class WallpaperCropActivity extends Activity { protected void cropImageAndSetWallpaper(Uri uri, OnBitmapCroppedHandler onBitmapCroppedHandler, final boolean finishActivityWhenDone) { // Get the crop - Point inSize = mCropView.getSourceDimensions(); - boolean ltr = mCropView.getLayoutDirection() == View.LAYOUT_DIRECTION_LTR; Point minDims = new Point(); @@ -260,12 +299,21 @@ public class WallpaperCropActivity extends Activity { } // Get the crop RectF cropRect = mCropView.getCrop(); + int cropRotation = mCropView.getImageRotation(); float cropScale = mCropView.getWidth() / (float) cropRect.width(); + Point inSize = mCropView.getSourceDimensions(); + Matrix rotateMatrix = new Matrix(); + rotateMatrix.setRotate(cropRotation); + float[] rotatedInSize = new float[] { inSize.x, inSize.y }; + rotateMatrix.mapPoints(rotatedInSize); + rotatedInSize[0] = Math.abs(rotatedInSize[0]); + rotatedInSize[1] = Math.abs(rotatedInSize[1]); + // ADJUST CROP WIDTH // Extend the crop all the way to the right, for parallax // (or all the way to the left, in RTL) - float extraSpace = ltr ? inSize.x - cropRect.right : cropRect.left; + float extraSpace = ltr ? rotatedInSize[0] - cropRect.right : cropRect.left; // Cap the amount of extra width float maxExtraSpace = defaultWallpaperWidth / cropScale - cropRect.width(); extraSpace = Math.min(extraSpace, maxExtraSpace); @@ -283,7 +331,7 @@ public class WallpaperCropActivity extends Activity { float extraPortraitHeight = portraitHeight / cropScale - cropRect.height(); float expandHeight = - Math.min(Math.min(inSize.y - cropRect.bottom, cropRect.top), + Math.min(Math.min(rotatedInSize[1] - cropRect.bottom, cropRect.top), extraPortraitHeight / 2); cropRect.top -= expandHeight; cropRect.bottom += expandHeight; @@ -301,7 +349,7 @@ public class WallpaperCropActivity extends Activity { } }; BitmapCropTask cropTask = new BitmapCropTask(this, uri, - cropRect, outWidth, outHeight, true, false, onEndCrop); + cropRect, cropRotation, outWidth, outHeight, true, false, onEndCrop); if (onBitmapCroppedHandler != null) { cropTask.setOnBitmapCropped(onBitmapCroppedHandler); } @@ -321,7 +369,7 @@ public class WallpaperCropActivity extends Activity { InputStream mInStream; RectF mCropBounds = null; int mOutWidth, mOutHeight; - int mRotation = 0; // for now + int mRotation; String mOutputFormat = "jpg"; // for now boolean mSetWallpaper; boolean mSaveCroppedBitmap; @@ -332,40 +380,45 @@ public class WallpaperCropActivity extends Activity { boolean mNoCrop; public BitmapCropTask(Context c, String filePath, - RectF cropBounds, int outWidth, int outHeight, + RectF cropBounds, int rotation, int outWidth, int outHeight, boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) { mContext = c; mInFilePath = filePath; - init(cropBounds, outWidth, outHeight, setWallpaper, saveCroppedBitmap, onEndRunnable); + init(cropBounds, rotation, + outWidth, outHeight, setWallpaper, saveCroppedBitmap, onEndRunnable); } public BitmapCropTask(byte[] imageBytes, - RectF cropBounds, int outWidth, int outHeight, + RectF cropBounds, int rotation, int outWidth, int outHeight, boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) { mInImageBytes = imageBytes; - init(cropBounds, outWidth, outHeight, setWallpaper, saveCroppedBitmap, onEndRunnable); + init(cropBounds, rotation, + outWidth, outHeight, setWallpaper, saveCroppedBitmap, onEndRunnable); } public BitmapCropTask(Context c, Uri inUri, - RectF cropBounds, int outWidth, int outHeight, + RectF cropBounds, int rotation, int outWidth, int outHeight, boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) { mContext = c; mInUri = inUri; - init(cropBounds, outWidth, outHeight, setWallpaper, saveCroppedBitmap, onEndRunnable); + init(cropBounds, rotation, + outWidth, outHeight, setWallpaper, saveCroppedBitmap, onEndRunnable); } public BitmapCropTask(Context c, Resources res, int inResId, - RectF cropBounds, int outWidth, int outHeight, + RectF cropBounds, int rotation, int outWidth, int outHeight, boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) { mContext = c; mInResId = inResId; mResources = res; - init(cropBounds, outWidth, outHeight, setWallpaper, saveCroppedBitmap, onEndRunnable); + init(cropBounds, rotation, + outWidth, outHeight, setWallpaper, saveCroppedBitmap, onEndRunnable); } - private void init(RectF cropBounds, int outWidth, int outHeight, + private void init(RectF cropBounds, int rotation, int outWidth, int outHeight, boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) { mCropBounds = cropBounds; + mRotation = rotation; mOutWidth = outWidth; mOutHeight = outHeight; mSetWallpaper = setWallpaper; @@ -452,6 +505,29 @@ public class WallpaperCropActivity extends Activity { if (mInStream != null) { // Find crop bounds (scaled to original image size) Rect roundedTrueCrop = new Rect(); + Matrix rotateMatrix = new Matrix(); + Matrix inverseRotateMatrix = new Matrix(); + if (mRotation > 0) { + rotateMatrix.setRotate(mRotation); + inverseRotateMatrix.setRotate(-mRotation); + + mCropBounds.roundOut(roundedTrueCrop); + mCropBounds = new RectF(roundedTrueCrop); + + Point bounds = getImageBounds(); + + float[] rotatedBounds = new float[] { bounds.x, bounds.y }; + rotateMatrix.mapPoints(rotatedBounds); + rotatedBounds[0] = Math.abs(rotatedBounds[0]); + rotatedBounds[1] = Math.abs(rotatedBounds[1]); + + mCropBounds.offset(-rotatedBounds[0]/2, -rotatedBounds[1]/2); + inverseRotateMatrix.mapRect(mCropBounds); + mCropBounds.offset(bounds.x/2, bounds.y/2); + + regenerateInputStream(); + } + mCropBounds.roundOut(roundedTrueCrop); if (roundedTrueCrop.width() <= 0 || roundedTrueCrop.height() <= 0) { @@ -495,6 +571,12 @@ public class WallpaperCropActivity extends Activity { fullSize = BitmapFactory.decodeStream(mInStream, null, options); } if (fullSize != null) { + mCropBounds.left /= scaleDownSampleSize; + mCropBounds.top /= scaleDownSampleSize; + mCropBounds.bottom /= scaleDownSampleSize; + mCropBounds.right /= scaleDownSampleSize; + mCropBounds.roundOut(roundedTrueCrop); + crop = Bitmap.createBitmap(fullSize, roundedTrueCrop.left, roundedTrueCrop.top, roundedTrueCrop.width(), roundedTrueCrop.height()); @@ -506,16 +588,40 @@ public class WallpaperCropActivity extends Activity { failure = true; return false; } - if (mOutWidth > 0 && mOutHeight > 0) { - Matrix m = new Matrix(); - RectF cropRect = new RectF(0, 0, crop.getWidth(), crop.getHeight()); - if (mRotation > 0) { - m.setRotate(mRotation); - m.mapRect(cropRect); + if (mOutWidth > 0 && mOutHeight > 0 || mRotation > 0) { + float[] dimsAfter = new float[] { crop.getWidth(), crop.getHeight() }; + rotateMatrix.mapPoints(dimsAfter); + dimsAfter[0] = Math.abs(dimsAfter[0]); + dimsAfter[1] = Math.abs(dimsAfter[1]); + + if (!(mOutWidth > 0 && mOutHeight > 0)) { + mOutWidth = Math.round(dimsAfter[0]); + mOutHeight = Math.round(dimsAfter[1]); } + + RectF cropRect = new RectF(0, 0, dimsAfter[0], dimsAfter[1]); RectF returnRect = new RectF(0, 0, mOutWidth, mOutHeight); - m.setRectToRect(cropRect, returnRect, Matrix.ScaleToFit.FILL); - m.preRotate(mRotation); + + Matrix m = new Matrix(); + if (mRotation == 0) { + m.setRectToRect(cropRect, returnRect, Matrix.ScaleToFit.FILL); + } else { + Matrix m1 = new Matrix(); + m1.setTranslate(-crop.getWidth() / 2f, -crop.getHeight() / 2f); + Matrix m2 = new Matrix(); + m2.setRotate(mRotation); + Matrix m3 = new Matrix(); + m3.setTranslate(dimsAfter[0] / 2f, dimsAfter[1] / 2f); + Matrix m4 = new Matrix(); + m4.setRectToRect(cropRect, returnRect, Matrix.ScaleToFit.FILL); + + Matrix c1 = new Matrix(); + c1.setConcat(m2, m1); + Matrix c2 = new Matrix(); + c2.setConcat(m4, m3); + m.setConcat(c2, c1); + } + Bitmap tmp = Bitmap.createBitmap((int) returnRect.width(), (int) returnRect.height(), Bitmap.Config.ARGB_8888); if (tmp != null) { @@ -525,14 +631,6 @@ public class WallpaperCropActivity extends Activity { c.drawBitmap(crop, m, p); crop = tmp; } - } else if (mRotation > 0) { - Matrix m = new Matrix(); - m.setRotate(mRotation); - Bitmap tmp = Bitmap.createBitmap(crop, 0, 0, crop.getWidth(), - crop.getHeight(), m, true); - if (tmp != null) { - crop = tmp; - } } if (mSaveCroppedBitmap) { @@ -601,8 +699,7 @@ public class WallpaperCropActivity extends Activity { final SharedPreferences sharedPrefs, WindowManager windowManager, final WallpaperManager wallpaperManager) { - final Point defaultWallpaperSize = - WallpaperCropActivity.getDefaultWallpaperSize(res, windowManager); + final Point defaultWallpaperSize = getDefaultWallpaperSize(res, windowManager); new Thread("suggestWallpaperDimension") { public void run() { @@ -614,7 +711,6 @@ public class WallpaperCropActivity extends Activity { }.start(); } - protected static RectF getMaxCropRect( int inWidth, int inHeight, int outWidth, int outHeight, boolean leftAligned) { RectF cropRect = new RectF(); diff --git a/src/com/android/launcher3/WallpaperPickerActivity.java b/src/com/android/launcher3/WallpaperPickerActivity.java index d3e1c7b76..9bf3c7773 100644 --- a/src/com/android/launcher3/WallpaperPickerActivity.java +++ b/src/com/android/launcher3/WallpaperPickerActivity.java @@ -30,6 +30,7 @@ import android.database.Cursor; import android.database.DataSetObserver; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.graphics.Matrix; import android.graphics.Point; import android.graphics.PorterDuff; import android.graphics.Rect; @@ -61,11 +62,14 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListAdapter; +import com.android.gallery3d.exif.ExifInterface; import com.android.photos.BitmapRegionTileSource; +import java.io.BufferedInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; public class WallpaperPickerActivity extends WallpaperCropActivity { @@ -126,8 +130,8 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { @Override public void onClick(WallpaperPickerActivity a) { CropView v = a.getCropView(); - v.setTileSource(new BitmapRegionTileSource( - a, mUri, 1024, 0), null); + int rotation = WallpaperCropActivity.getRotationFromExif(a, mUri); + v.setTileSource(new BitmapRegionTileSource(a, mUri, 1024, rotation), null); v.setTouchEnabled(true); } @Override @@ -136,8 +140,9 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { OnBitmapCroppedHandler h = new OnBitmapCroppedHandler() { public void onBitmapCropped(byte[] imageBytes) { Point thumbSize = getDefaultThumbnailSize(a.getResources()); - Bitmap thumb = - createThumbnail(thumbSize, null, null, imageBytes, null, 0, true); + // rotation is set to 0 since imageBytes has already been correctly rotated + Bitmap thumb = createThumbnail( + thumbSize, null, null, imageBytes, null, 0, 0, true); a.getSavedImages().writeImage(thumb, imageBytes); } }; @@ -165,8 +170,9 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { } @Override public void onClick(WallpaperPickerActivity a) { + int rotation = WallpaperCropActivity.getRotationFromExif(mResources, mResId); BitmapRegionTileSource source = new BitmapRegionTileSource( - mResources, a, mResId, 1024, 0); + mResources, a, mResId, 1024, rotation); CropView v = a.getCropView(); v.setTileSource(source, null); Point wallpaperSize = WallpaperCropActivity.getDefaultWallpaperSize( @@ -199,7 +205,6 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { // called by onCreate; this is subclassed to overwrite WallpaperCropActivity protected void init() { setContentView(R.layout.wallpaper_picker); - final WallpaperRootView root = (WallpaperRootView) findViewById(R.id.wallpaper_root); mCropView = (CropView) findViewById(R.id.cropView); mWallpaperStrip = findViewById(R.id.wallpaper_strip); @@ -522,7 +527,6 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { private void updateTileIndices() { LinearLayout masterWallpaperList = (LinearLayout) findViewById(R.id.master_wallpaper_list); final int childCount = masterWallpaperList.getChildCount(); - ArrayList<WallpaperTileInfo> tiles = new ArrayList<WallpaperTileInfo>(); final Resources res = getResources(); // Do two passes; the first pass gets the total number of tiles @@ -568,26 +572,35 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { } private static Bitmap createThumbnail(Point size, Context context, Uri uri, byte[] imageBytes, - Resources res, int resId, boolean leftAligned) { + Resources res, int resId, int rotation, boolean leftAligned) { int width = size.x; int height = size.y; BitmapCropTask cropTask; if (uri != null) { - cropTask = new BitmapCropTask(context, uri, null, width, height, false, true, null); + cropTask = new BitmapCropTask( + context, uri, null, rotation, width, height, false, true, null); } else if (imageBytes != null) { - cropTask = new BitmapCropTask(imageBytes, null, width, height, false, true, null); + cropTask = new BitmapCropTask( + imageBytes, null, rotation, width, height, false, true, null); } else { - cropTask = - new BitmapCropTask(context, res, resId, null, width, height, false, true, null); + cropTask = new BitmapCropTask( + context, res, resId, null, rotation, width, height, false, true, null); } Point bounds = cropTask.getImageBounds(); if (bounds == null || bounds.x == 0 || bounds.y == 0) { return null; } + Matrix rotateMatrix = new Matrix(); + rotateMatrix.setRotate(rotation); + float[] rotatedBounds = new float[] { bounds.x, bounds.y }; + rotateMatrix.mapPoints(rotatedBounds); + rotatedBounds[0] = Math.abs(rotatedBounds[0]); + rotatedBounds[1] = Math.abs(rotatedBounds[1]); + RectF cropRect = WallpaperCropActivity.getMaxCropRect( - bounds.x, bounds.y, width, height, leftAligned); + (int) rotatedBounds[0], (int) rotatedBounds[1], width, height, leftAligned); cropTask.setCropBounds(cropRect); if (cropTask.cropBitmap()) { @@ -607,7 +620,8 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { // Load the thumbnail ImageView image = (ImageView) pickedImageThumbnail.findViewById(R.id.wallpaper_image); Point defaultSize = getDefaultThumbnailSize(this.getResources()); - Bitmap thumb = createThumbnail(defaultSize, this, uri, null, null, 0, false); + int rotation = WallpaperCropActivity.getRotationFromExif(this, uri); + Bitmap thumb = createThumbnail(defaultSize, this, uri, null, null, 0, rotation, false); if (thumb != null) { image.setImageBitmap(thumb); Drawable thumbDrawable = image.getDrawable(); @@ -620,6 +634,7 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { UriWallpaperInfo info = new UriWallpaperInfo(uri); pickedImageThumbnail.setTag(info); info.setView(pickedImageThumbnail); + addLongPressHandler(pickedImageThumbnail); updateTileIndices(); pickedImageThumbnail.setOnClickListener(mThumbnailOnClickListener); mThumbnailOnClickListener.onClick(pickedImageThumbnail); @@ -690,8 +705,11 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { thumb = BitmapFactory.decodeFile(defaultThumbFile.getAbsolutePath()); defaultWallpaperExists = true; } else { - Point defaultThumbSize = getDefaultThumbnailSize(getResources()); - thumb = createThumbnail(defaultThumbSize, this, null, null, sysRes, resId, false); + Resources res = getResources(); + Point defaultThumbSize = getDefaultThumbnailSize(res); + int rotation = WallpaperCropActivity.getRotationFromExif(res, resId); + thumb = createThumbnail( + defaultThumbSize, this, null, null, sysRes, resId, rotation, false); if (thumb != null) { try { defaultThumbFile.createNewFile(); diff --git a/src/com/android/photos/views/TiledImageView.java b/src/com/android/photos/views/TiledImageView.java index 36cb4384d..af4199c91 100644 --- a/src/com/android/photos/views/TiledImageView.java +++ b/src/com/android/photos/views/TiledImageView.java @@ -63,7 +63,7 @@ public class TiledImageView extends FrameLayout { // Guarded by locks public float scale; public int centerX, centerY; - int rotation; + public int rotation; public TileSource source; Runnable isReadyCallback; |