summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authornicolasroard <nicolasroard@google.com>2013-09-10 13:58:30 -0700
committernicolasroard <nicolasroard@google.com>2013-09-12 08:26:23 -0700
commit34e8432353acb0c45253cf4ef855512c7472019b (patch)
tree8ed962acfb79b11746373d65763a9f7c7f10523e /src
parent5d727d85d58ad03edbcdd62c533bb14fdd5dda19 (diff)
downloadandroid_packages_apps_Gallery2-34e8432353acb0c45253cf4ef855512c7472019b.tar.gz
android_packages_apps_Gallery2-34e8432353acb0c45253cf4ef855512c7472019b.tar.bz2
android_packages_apps_Gallery2-34e8432353acb0c45253cf4ef855512c7472019b.zip
Fix full-res geometry
Change-Id: I25f2fde1031ba7d896c82484a3da0ea03bcff7b8
Diffstat (limited to 'src')
-rw-r--r--src/com/android/gallery3d/filtershow/cache/ImageLoader.java30
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/ImageShow.java145
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/MasterImage.java85
-rw-r--r--src/com/android/gallery3d/filtershow/pipeline/CachingPipeline.java2
4 files changed, 161 insertions, 101 deletions
diff --git a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java b/src/com/android/gallery3d/filtershow/cache/ImageLoader.java
index 92942d4fc..3f9df23b6 100644
--- a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java
+++ b/src/com/android/gallery3d/filtershow/cache/ImageLoader.java
@@ -65,7 +65,7 @@ public final class ImageLoader {
public static final int ORI_TRANSVERSE = ExifInterface.Orientation.LEFT_BOTTOM;
private static final int BITMAP_LOAD_BACKOUT_ATTEMPTS = 5;
-
+ private static final float OVERDRAW_ZOOM = 1.2f;
private ImageLoader() {}
/**
@@ -235,7 +235,7 @@ public final class ImageLoader {
* if it is a subset of the bitmap stored at uri. Otherwise returns
* null.
*/
- public static Bitmap loadRegionBitmap(Context context, FilterEnvironment environment,
+ public static Bitmap loadRegionBitmap(Context context, BitmapCache cache,
Uri uri, BitmapFactory.Options options,
Rect bounds) {
InputStream is = null;
@@ -254,23 +254,15 @@ public final class ImageLoader {
// return null if bounds are not entirely within the bitmap
if (!r.contains(imageBounds)) {
imageBounds.intersect(r);
+ bounds.left = imageBounds.left;
+ bounds.top = imageBounds.top;
}
- Bitmap reuse = environment.getBitmap(imageBounds.width(),
+ Bitmap reuse = cache.getBitmap(imageBounds.width(),
imageBounds.height(), BitmapCache.REGION);
options.inBitmap = reuse;
Bitmap bitmap = decoder.decodeRegion(imageBounds, options);
if (bitmap != reuse) {
- environment.cache(reuse); // not reused, put back in cache
- }
- if (imageBounds.width() != bounds.width() || imageBounds.height() != bounds.height()) {
- Bitmap temp = environment.getBitmap(bounds.width(),
- bounds.height(), BitmapCache.REGION);
- Canvas canvas = new Canvas(temp);
- canvas.drawARGB(0, 0, 0, 0);
- float dx = imageBounds.left - bounds.left;
- float dy = imageBounds.top - bounds.top;
- canvas.drawBitmap(bitmap, dx, dy, null);
- return temp;
+ cache.cache(reuse); // not reused, put back in cache
}
return bitmap;
} catch (FileNotFoundException e) {
@@ -404,24 +396,24 @@ public final class ImageLoader {
}
public static Bitmap getScaleOneImageForPreset(Context context,
- FilterEnvironment environment,
+ BitmapCache cache,
Uri uri, Rect bounds,
Rect destination) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inMutable = true;
if (destination != null) {
- if (bounds.width() > destination.width()) {
+ int thresholdWidth = (int) (destination.width() * OVERDRAW_ZOOM);
+ if (bounds.width() > thresholdWidth) {
int sampleSize = 1;
int w = bounds.width();
- while (w > destination.width()) {
+ while (w > thresholdWidth) {
sampleSize *= 2;
w /= sampleSize;
}
options.inSampleSize = sampleSize;
}
}
- Bitmap bmp = loadRegionBitmap(context, environment, uri, options, bounds);
- return bmp;
+ return loadRegionBitmap(context, cache, uri, options, bounds);
}
/**
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java b/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java
index 56fdd7d67..3234c2516 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java
@@ -27,10 +27,10 @@ import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
+import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.NinePatchDrawable;
import android.util.AttributeSet;
-import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.OnDoubleTapListener;
import android.view.GestureDetector.OnGestureListener;
@@ -49,7 +49,6 @@ import com.android.gallery3d.filtershow.tools.SaveImage;
import java.io.File;
import java.util.ArrayList;
-import java.util.Collection;
public class ImageShow extends View implements OnGestureListener,
ScaleGestureDetector.OnScaleGestureListener,
@@ -233,6 +232,9 @@ public class ImageShow extends View implements OnGestureListener,
@Override
public void onDraw(Canvas canvas) {
+ mPaint.reset();
+ mPaint.setAntiAlias(true);
+ mPaint.setFilterBitmap(true);
MasterImage.getImage().setImageShowSize(
getWidth() - 2*mShadowMargin,
getHeight() - 2*mShadowMargin);
@@ -248,53 +250,43 @@ public class ImageShow extends View implements OnGestureListener,
} else if (img.getLoadedPreset() != null) {
return;
}
+ mActivity.stopLoadingIndicator();
}
- float cx = canvas.getWidth()/2.0f;
- float cy = canvas.getHeight()/2.0f;
- float scaleFactor = MasterImage.getImage().getScaleFactor();
- Point translation = MasterImage.getImage().getTranslation();
-
canvas.save();
mShadowDrawn = false;
- canvas.save();
- // TODO: center scale on gesture
- canvas.scale(scaleFactor, scaleFactor, cx, cy);
- canvas.translate(translation.x, translation.y);
Bitmap highresPreview = MasterImage.getImage().getHighresImage();
+ Bitmap fullHighres = MasterImage.getImage().getPartialImage();
boolean isDoingNewLookAnimation = MasterImage.getImage().onGoingNewLookAnimation();
- if (!isDoingNewLookAnimation && highresPreview != null) {
- drawImage(canvas, highresPreview, true);
+ if (highresPreview == null || isDoingNewLookAnimation) {
+ drawImageAndAnimate(canvas, getFilteredImage());
} else {
- drawImage(canvas, getFilteredImage(), true);
+ drawImageAndAnimate(canvas, highresPreview);
}
- canvas.restore();
- Bitmap partialPreview = MasterImage.getImage().getPartialImage();
- if (!isDoingNewLookAnimation && partialPreview != null) {
- canvas.save();
- Rect originalBounds = MasterImage.getImage().getOriginalBounds();
- Collection<FilterRepresentation> geo = MasterImage.getImage().getPreset()
- .getGeometryFilters();
-
- Matrix compensation = GeometryMathUtils.getPartialToScreenMatrix(geo,
- originalBounds, getWidth(), getHeight(),
- partialPreview.getWidth(), partialPreview.getHeight());
- canvas.drawBitmap(partialPreview, compensation, null);
- canvas.restore();
- }
+ drawHighresImage(canvas, fullHighres);
+ drawCompareImage(canvas, getGeometryOnlyImage());
- canvas.save();
- canvas.scale(scaleFactor, scaleFactor, cx, cy);
- canvas.translate(translation.x, translation.y);
- drawPartialImage(canvas, getGeometryOnlyImage());
canvas.restore();
+ }
- canvas.restore();
+ private void drawHighresImage(Canvas canvas, Bitmap fullHighres) {
+ Matrix originalToScreen = MasterImage.getImage().originalImageToScreen();
+ if (fullHighres != null && originalToScreen != null) {
+ Matrix screenToOriginal = new Matrix();
+ originalToScreen.invert(screenToOriginal);
+ Rect rBounds = new Rect();
+ rBounds.set(MasterImage.getImage().getPartialBounds());
+ if (fullHighres != null) {
+ originalToScreen.preTranslate(rBounds.left, rBounds.top);
+ canvas.clipRect(mImageBounds);
+ canvas.drawBitmap(fullHighres, originalToScreen, mPaint);
+ }
+ }
}
public void resetImageCaches(ImageShow caller) {
@@ -313,56 +305,68 @@ public class ImageShow extends View implements OnGestureListener,
return MasterImage.getImage().getFilteredImage();
}
- public void drawImage(Canvas canvas, Bitmap image, boolean updateBounds) {
+ public void drawImageAndAnimate(Canvas canvas,
+ Bitmap image) {
if (image == null) {
return;
}
-
- Rect d = computeImageBounds(image.getWidth(), image.getHeight());
-
- if (updateBounds) {
- mImageBounds = d;
+ Matrix m = MasterImage.getImage().computeImageToScreen(image, 0, false);
+ if (m == null) {
+ return;
}
- float centerX = mShadowMargin + (getWidth() - 2 * mShadowMargin) / 2;
- float centerY = mShadowMargin + (getHeight() - 2 * mShadowMargin) / 2;
-
- MasterImage master = MasterImage.getImage();
canvas.save();
+ MasterImage master = MasterImage.getImage();
+
+ RectF d = new RectF(0, 0, image.getWidth(), image.getHeight());
+ m.mapRect(d);
+ d.roundOut(mImageBounds);
+
if (master.onGoingNewLookAnimation()
|| mDidStartAnimation) {
mDidStartAnimation = true;
+ canvas.save();
+
+ // Animation uses the image before the change
+ Bitmap previousImage = master.getPreviousImage();
+ Matrix mp = MasterImage.getImage().computeImageToScreen(previousImage, 0, false);
+ RectF dp = new RectF(0, 0, previousImage.getWidth(), previousImage.getHeight());
+ mp.mapRect(dp);
+ Rect previousBounds = new Rect();
+ dp.roundOut(previousBounds);
+ float centerX = dp.centerX();
+ float centerY = dp.centerY();
+ boolean needsToDrawImage = true;
+
if (master.getCurrentLookAnimation()
- == MasterImage.CIRCLE_ANIMATION
- && MasterImage.getImage().getPreviousImage() != null) {
+ == MasterImage.CIRCLE_ANIMATION) {
float maskScale = MasterImage.getImage().getMaskScale();
if (maskScale >= 0.0f) {
float maskW = sMask.getWidth() / 2.0f;
float maskH = sMask.getHeight() / 2.0f;
- float x = centerX - maskW * maskScale;
- float y = centerY - maskH * maskScale;
Point point = mActivity.hintTouchPoint(this);
- x = point.x - maskW * maskScale;
- y = point.y - maskH * maskScale;
+ float x = point.x - maskW * maskScale;
+ float y = point.y - maskH * maskScale;
// Prepare the shader
mShaderMatrix.reset();
mShaderMatrix.setScale(1.0f / maskScale, 1.0f / maskScale);
- mShaderMatrix.preTranslate(-x + d.left, -y + d.top);
- float scaleImageX = d.width() / (float) image.getWidth();
- float scaleImageY = d.height() / (float) image.getHeight();
+ mShaderMatrix.preTranslate(-x + mImageBounds.left, -y + mImageBounds.top);
+ float scaleImageX = mImageBounds.width() / (float) image.getWidth();
+ float scaleImageY = mImageBounds.height() / (float) image.getHeight();
mShaderMatrix.preScale(scaleImageX, scaleImageY);
mMaskPaint.reset();
mMaskPaint.setShader(createShader(image));
mMaskPaint.getShader().setLocalMatrix(mShaderMatrix);
- drawImage(canvas, MasterImage.getImage().getPreviousImage());
+ drawShadow(canvas, mImageBounds); // as needed
+ canvas.drawBitmap(previousImage, m, mPaint);
+ canvas.clipRect(mImageBounds);
canvas.translate(x, y);
canvas.scale(maskScale, maskScale);
canvas.drawBitmap(sMask, 0, 0, mMaskPaint);
- } else {
- drawImage(canvas, image);
+ needsToDrawImage = false;
}
} else if (master.getCurrentLookAnimation()
== MasterImage.ROTATE_ANIMATION) {
@@ -375,7 +379,6 @@ public class ImageShow extends View implements OnGestureListener,
+ (finalScale * master.getAnimFraction());
canvas.rotate(master.getAnimRotationValue(), centerX, centerY);
canvas.scale(finalScale, finalScale, centerX, centerY);
- drawImage(canvas, master.getPreviousImage());
} else if (master.getCurrentLookAnimation()
== MasterImage.MIRROR_ANIMATION) {
if (master.getCurrentFilterRepresentation()
@@ -411,10 +414,17 @@ public class ImageShow extends View implements OnGestureListener,
}
}
}
- drawImage(canvas, master.getPreviousImage());
}
+
+ if (needsToDrawImage) {
+ drawShadow(canvas, previousBounds); // as needed
+ canvas.drawBitmap(previousImage, mp, mPaint);
+ }
+
+ canvas.restore();
} else {
- drawImage(canvas, image);
+ drawShadow(canvas, mImageBounds); // as needed
+ canvas.drawBitmap(image, m, mPaint);
}
if (!master.onGoingNewLookAnimation()
@@ -423,19 +433,8 @@ public class ImageShow extends View implements OnGestureListener,
mDidStartAnimation = false;
MasterImage.getImage().resetAnimBitmap();
}
- canvas.restore();
- }
- private void drawImage(Canvas canvas, Bitmap image) {
- Rect d = computeImageBounds(image.getWidth(), image.getHeight());
- float scaleImageX = d.width() / (float) image.getWidth();
- float scaleImageY = d.height() / (float) image.getHeight();
- Matrix imageMatrix = new Matrix();
- imageMatrix.postScale(scaleImageX, scaleImageY);
- imageMatrix.postTranslate(d.left, d.top);
- drawShadow(canvas, d);
- canvas.clipRect(d);
- canvas.drawBitmap(image, imageMatrix, mPaint);
+ canvas.restore();
}
private Rect computeImageBounds(int imageWidth, int imageHeight) {
@@ -462,7 +461,7 @@ public class ImageShow extends View implements OnGestureListener,
}
}
- public void drawPartialImage(Canvas canvas, Bitmap image) {
+ public void drawCompareImage(Canvas canvas, Bitmap image) {
boolean showsOriginal = MasterImage.getImage().showsOriginal();
if (!showsOriginal && !mTouchShowOriginal)
return;
@@ -503,7 +502,8 @@ public class ImageShow extends View implements OnGestureListener,
}
}
canvas.clipRect(d);
- drawImage(canvas, image, false);
+ Matrix m = MasterImage.getImage().computeImageToScreen(image, 0, false);
+ canvas.drawBitmap(image, m, mPaint);
Paint paint = new Paint();
paint.setColor(Color.BLACK);
paint.setStrokeWidth(3);
@@ -658,7 +658,6 @@ public class ImageShow extends View implements OnGestureListener,
translation.y = (int) (Math.signum(translation.y) *
maxTranslationY);
}
-
}
}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java b/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java
index e0f328746..bad2012b6 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java
@@ -25,7 +25,6 @@ import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import android.net.Uri;
-import android.util.Log;
import com.android.gallery3d.exif.ExifTag;
import com.android.gallery3d.filtershow.FilterShowActivity;
@@ -85,6 +84,8 @@ public class MasterImage implements RenderingRequestCaller {
private Bitmap mHighresBitmap = null;
private Bitmap mPreviousImage = null;
private ImagePreset mPreviousPreset = null;
+ private int mShadowMargin = 15; // not scaled, fixed in the asset
+ private Rect mPartialBounds = new Rect();
private ValueAnimator mAnimator = null;
private float mMaskScale = 1;
@@ -360,6 +361,10 @@ public class MasterImage implements RenderingRequestCaller {
return mPartialBitmap;
}
+ public Rect getPartialBounds() {
+ return mPartialBounds;
+ }
+
public Bitmap getHighresImage() {
if (mHighresBitmap == null) {
return getFilteredImage();
@@ -470,6 +475,7 @@ public class MasterImage implements RenderingRequestCaller {
mOnGoingNewLookAnimation = false;
mCurrentAnimRotationStartValue = 0;
mAnimator = null;
+ notifyObservers();
}
@Override
@@ -566,11 +572,66 @@ public class MasterImage implements RenderingRequestCaller {
public void setImageShowSize(int w, int h) {
if (mImageShowSize.x != w || mImageShowSize.y != h) {
mImageShowSize.set(w, h);
+ float maxWidth = mOriginalBounds.width() / (float) w;
+ float maxHeight = mOriginalBounds.height() / (float) h;
+ mMaxScaleFactor = Math.max(3.f, Math.max(maxWidth, maxHeight));
needsUpdatePartialPreview();
needsUpdateHighResPreview();
}
}
+ public Matrix originalImageToScreen() {
+ return computeImageToScreen(null, 0, true);
+ }
+
+ public Matrix computeImageToScreen(Bitmap bitmapToDraw,
+ float rotate,
+ boolean applyGeometry) {
+ if (getOriginalBounds() == null
+ || mImageShowSize.x == 0
+ || mImageShowSize.y == 0) {
+ return null;
+ }
+
+ Matrix m = null;
+ float scale = 1f;
+ float translateX = 0;
+ float translateY = 0;
+
+ if (applyGeometry) {
+ GeometryMathUtils.GeometryHolder holder = GeometryMathUtils.unpackGeometry(
+ mPreset.getGeometryFilters());
+ m = GeometryMathUtils.getCropSelectionToScreenMatrix(null, holder,
+ getOriginalBounds().width(), getOriginalBounds().height(),
+ mImageShowSize.x, mImageShowSize.y);
+ } else if (bitmapToDraw != null) {
+ m = new Matrix();
+ RectF size = new RectF(0, 0,
+ bitmapToDraw.getWidth(),
+ bitmapToDraw.getHeight());
+ scale = mImageShowSize.x / size.width();
+ if (size.width() < size.height()) {
+ scale = mImageShowSize.y / size.height();
+ }
+ translateX = (mImageShowSize.x - (size.width() * scale)) / 2.0f;
+ translateY = (mImageShowSize.y - (size.height() * scale)) / 2.0f;
+ } else {
+ return null;
+ }
+
+ Point translation = getTranslation();
+ m.postScale(scale, scale);
+ m.postRotate(rotate, mImageShowSize.x / 2.0f, mImageShowSize.y / 2.0f);
+ m.postTranslate(translateX, translateY);
+ m.postTranslate(mShadowMargin, mShadowMargin);
+ m.postScale(getScaleFactor(), getScaleFactor(),
+ mImageShowSize.x / 2.0f,
+ mImageShowSize.y / 2.0f);
+ m.postTranslate(translation.x * getScaleFactor(),
+ translation.y * getScaleFactor());
+ return m;
+ }
+
private Matrix getImageToScreenMatrix(boolean reflectRotation) {
if (getOriginalBounds() == null || mImageShowSize.x == 0 || mImageShowSize.y == 0) {
return new Matrix();
@@ -619,14 +680,21 @@ public class MasterImage implements RenderingRequestCaller {
invalidatePartialPreview();
return;
}
- Matrix m = getScreenToImageMatrix(true);
- RectF r = new RectF(0, 0, mImageShowSize.x, mImageShowSize.y);
- RectF dest = new RectF();
- m.mapRect(dest, r);
- Rect bounds = new Rect();
- dest.roundOut(bounds);
+ Matrix originalToScreen = MasterImage.getImage().originalImageToScreen();
+ if (originalToScreen == null) {
+ return;
+ }
+ Matrix screenToOriginal = new Matrix();
+ originalToScreen.invert(screenToOriginal);
+ RectF bounds = new RectF(0, 0,
+ mImageShowSize.x + 2 * mShadowMargin,
+ mImageShowSize.y + 2 * mShadowMargin);
+ screenToOriginal.mapRect(bounds);
+ Rect rBounds = new Rect();
+ bounds.roundOut(rBounds);
+
mActivity.getProcessingService().postFullresRenderingRequest(mPreset,
- getScaleFactor(), bounds,
+ getScaleFactor(), rBounds,
new Rect(0, 0, mImageShowSize.x, mImageShowSize.y), this);
invalidatePartialPreview();
}
@@ -653,6 +721,7 @@ public class MasterImage implements RenderingRequestCaller {
&& request.getScaleFactor() == getScaleFactor()) {
mBitmapCache.cache(mPartialBitmap);
mPartialBitmap = request.getBitmap();
+ mPartialBounds.set(request.getBounds());
notifyObservers();
needsCheckModification = true;
}
diff --git a/src/com/android/gallery3d/filtershow/pipeline/CachingPipeline.java b/src/com/android/gallery3d/filtershow/pipeline/CachingPipeline.java
index 2a4b09952..07ab14ac9 100644
--- a/src/com/android/gallery3d/filtershow/pipeline/CachingPipeline.java
+++ b/src/com/android/gallery3d/filtershow/pipeline/CachingPipeline.java
@@ -306,7 +306,7 @@ public class CachingPipeline implements PipelineInterface {
if (request.getType() == RenderingRequest.PARTIAL_RENDERING) {
MasterImage master = MasterImage.getImage();
bitmap = ImageLoader.getScaleOneImageForPreset(master.getActivity(),
- mEnvironment,
+ mEnvironment.getBimapCache(),
master.getUri(), request.getBounds(),
request.getDestination());
if (bitmap == null) {