import com.android.gallery3d.filtershow.filters.ImageFilterGeometry;
-/**
- * This class holds metadata about an image's geometry. Specifically: rotation,
- * scaling, cropping, and image boundaries. It maintains the invariant that the
- * cropping boundaries are within or equal to the image boundaries (before
- * rotation) WHEN mSafe is true.
- */
-
public class GeometryMetadata {
// Applied in order: rotate, crop, scale.
// Do not scale saved image (presumably?).
private final RectF mCropBounds = new RectF();
private final RectF mPhotoBounds = new RectF();
private FLIP mFlip = FLIP.NONE;
- private boolean mSafe = false;
- private Matrix mMatrix = new Matrix();
private RectF mBounds = new RectF();
return m;
}
- // Safe as long as invariant holds.
public void set(GeometryMetadata g) {
mScaleFactor = g.mScaleFactor;
mRotation = g.mRotation;
mCropBounds.set(g.mCropBounds);
mPhotoBounds.set(g.mPhotoBounds);
mFlip = g.mFlip;
- mSafe = g.mSafe;
- mMatrix = g.mMatrix;
mBounds = g.mBounds;
}
return new RectF(mPhotoBounds);
}
- public boolean safe() {
- return mSafe;
- }
public void setScaleFactor(float scale) {
mScaleFactor = scale;
mStraightenRotation = straighten;
}
- /**
- * Sets crop bounds to be the intersection of mPhotoBounds and the new crop
- * bounds. If there was no intersection, returns false and does not set crop
- * bounds
- */
- public boolean safeSetCropBounds(RectF newCropBounds) {
- if (mCropBounds.setIntersect(newCropBounds, mPhotoBounds)) {
- mSafe = true;
- return true;
- }
- return false;
- }
-
public void setCropBounds(RectF newCropBounds) {
mCropBounds.set(newCropBounds);
- mSafe = false;
- }
-
- /**
- * Sets mPhotoBounds to be the new photo bounds and sets mCropBounds to be
- * the intersection of the new photo bounds and the old crop bounds. Sets
- * the crop bounds to mPhotoBounds if there is no intersection.
- */
-
- public void safeSetPhotoBounds(RectF newPhotoBounds) {
- mPhotoBounds.set(newPhotoBounds);
- if (!mCropBounds.intersect(mPhotoBounds)) {
- mCropBounds.set(mPhotoBounds);
- }
- mSafe = true;
}
public void setPhotoBounds(RectF newPhotoBounds) {
mPhotoBounds.set(newPhotoBounds);
- mSafe = false;
}
public boolean cropFitsInPhoto(RectF cropBounds) {
return (mScaleFactor == d.mScaleFactor &&
mRotation == d.mRotation &&
mStraightenRotation == d.mStraightenRotation &&
- mFlip == d.mFlip && mSafe == d.mSafe &&
+ mFlip == d.mFlip &&
mCropBounds.equals(d.mCropBounds) && mPhotoBounds.equals(d.mPhotoBounds));
}
result = 31 * result + mFlip.hashCode();
result = 31 * result + mCropBounds.hashCode();
result = 31 * result + mPhotoBounds.hashCode();
- result = 31 * result + (mSafe ? 1 : 0);
return result;
}
@Override
public String toString() {
return getClass().getName() + "[" + "scale=" + mScaleFactor
- + ",rotation=" + mRotation + ",flip=" + mFlip + ",safe="
- + (mSafe ? "true" : "false") + ",straighten="
+ + ",rotation=" + mRotation + ",flip=" + mFlip + ",straighten="
+ mStraightenRotation + ",cropRect=" + mCropBounds.toShortString()
+ ",photoRect=" + mPhotoBounds.toShortString() + "]";
}
}
}
- public Matrix getMatrix() {
- return mMatrix;
+ public boolean hasSwitchedWidthHeight(){
+ return (((int) (mRotation / 90)) % 2) != 0;
+ }
+
+ public Matrix buildGeometryMatrix(float width, float height, float scaling, float dx, float dy){
+ float dx0 = width/2;
+ float dy0 = height/2;
+ Matrix m = getFlipMatrix(width, height);
+ m.postTranslate(-dx0, -dy0);
+ float rot = mRotation % 360;
+ if (rot < 0)
+ rot += 360;
+ m.postRotate(rot + mStraightenRotation);
+ m.postScale(scaling, scaling);
+ m.postTranslate(dx, dy);
+ return m;
+ }
+
+ public Matrix buildGeometryUIMatrix(float scaling, float dx, float dy){
+ float w = mPhotoBounds.width();
+ float h = mPhotoBounds.height();
+ return buildGeometryMatrix(w, h, scaling, dx, dy);
}
}
protected float mTouchCenterX;
protected float mTouchCenterY;
- private Matrix mLocalMatrix = null;
-
// Local geometry data
private GeometryMetadata mLocalGeoMetadata = null;
private RectF mLocalDisplayBounds = null;
mCenterY = displayHeight / 2;
mYOffset = (displayHeight - imageHeight) / 2.0f;
mXOffset = (displayWidth - imageWidth) / 2.0f;
-
- float zoom = computeScale(mLocalDisplayBounds.width(), mLocalDisplayBounds.height());
- mLocalGeoMetadata.setScaleFactor(zoom);
}
@Override
protected void syncLocalToMasterGeometry() {
mLocalGeoMetadata = getMaster().getGeometry();
calculateLocalScalingFactorAndOffset();
- mLocalMatrix = mLocalGeoMetadata.getMatrix();
- }
-
- public Matrix getLocalMatrix() {
- return mLocalMatrix;
}
protected RectF getLocalPhotoBounds() {
mLocalGeoMetadata.setScaleFactor(s);
}
- protected void updateMatrix() {
+ protected void updateScale(){
RectF bounds = getUntranslatedStraightenCropBounds(mLocalGeoMetadata.getPhotoBounds(),
getLocalStraighten());
float zoom = computeScale(bounds.width(), bounds.height());
setLocalScale(zoom);
- float w = mLocalGeoMetadata.getPhotoBounds().width();
- float h = mLocalGeoMetadata.getPhotoBounds().height();
- float ratio = h / w;
- float rcenterx = 0.5f;
- float rcentery = 0.5f * ratio;
- Matrix flipper = mLocalGeoMetadata.getFlipMatrix(1.0f, ratio);
- mLocalMatrix.reset();
- mLocalMatrix.postConcat(flipper);
- mLocalMatrix.postRotate(getTotalLocalRotation(), rcenterx, rcentery);
- invalidate();
}
protected void setLocalRotation(float r) {
mLocalGeoMetadata.setRotation(r);
- updateMatrix();
+ updateScale();
+ }
+
+ private Matrix getLocalGeoMatrix(float scaling, float dx, float dy) {
+ return mLocalGeoMetadata.buildGeometryUIMatrix(scaling, dx, dy);
}
protected void setLocalStraighten(float r) {
mLocalGeoMetadata.setStraightenRotation(r);
- updateMatrix();
+ updateScale();
}
protected void setLocalCropBounds(RectF c) {
protected void setLocalFlip(FLIP flip) {
mLocalGeoMetadata.setFlipType(flip);
- updateMatrix();
}
protected float getTotalLocalRotation() {
// Returns maximal rectangular crop bound that still fits within
// the image bound after the image has been rotated.
- protected static RectF findCropBoundForRotatedImg(RectF cropBound,
- RectF imageBound,
- float rotation,
- float centerX,
- float centerY) {
+ protected static RectF findCropBoundForRotatedImg(RectF cropBound, RectF imageBound,
+ float rotation, float centerX, float centerY) {
Matrix m = new Matrix();
float[] cropEdges = getCornersFromRect(cropBound);
m.setRotate(rotation, centerX, centerY);
return height * w / h;
}
- protected void logMasterGeo() {
- Log.v(LOGTAG, getMaster().getGeometry().toString());
- }
-
@Override
protected void onVisibilityChanged(View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility);
mVisibilityGained = true;
syncLocalToMasterGeometry();
gainedVisibility();
- logMasterGeo();
} else {
if (mVisibilityGained == true && mHasDrawn == true) {
lostVisibility();
- logMasterGeo();
}
mVisibilityGained = false;
mHasDrawn = false;
protected void gainedVisibility() {
// TODO: Override this stub.
- updateMatrix();
+ updateScale();
}
protected void lostVisibility() {
setActionUp();
saveAndSetPreset();
Log.v(LOGTAG, "up action");
- logMasterGeo();
break;
case (MotionEvent.ACTION_MOVE):
setActionMove(event.getX(), event.getY());
}
public Matrix computeBoundsMatrix(Bitmap bitmap) {
+ float w = getWidth();
+ float h = getHeight();
Matrix boundsMatrix = new Matrix();
boundsMatrix.setTranslate((getWidth() - bitmap.getWidth()) / 2.0f,
(getHeight() - bitmap.getHeight()) / 2.0f);
boundsMatrix.postRotate(getLocalRotation(), getWidth() / 2.0f, getHeight() / 2.0f);
+ float scale = computeScale(w, h);
+ boundsMatrix.postScale(scale, scale, getWidth()/2, getHeight()/2);
return boundsMatrix;
}
return transformedBounds;
}
+ protected void drawImage(Canvas canvas, Bitmap bitmap, Paint paint) {
+ float scale = computeScale(getWidth(), getHeight());
+ float yoff = getHeight()/2;
+ float xoff = getWidth()/2;
+ Matrix m = getLocalGeoMatrix(scale, xoff, yoff);
+ canvas.save();
+ canvas.drawBitmap(bitmap, m, paint);
+ }
+
protected void drawTransformedBitmap(Canvas canvas, Bitmap bitmap, Paint paint, boolean clip) {
+ float w = getWidth();
+ float h = getHeight();
Matrix boundsMatrix = computeBoundsMatrix(bitmap);
RectF bounds = getUntranslatedStraightenCropBounds(getLocalPhotoBounds(),
getLocalStraighten());
RectF transformedBounds = new RectF(bounds);
boundsMatrix.mapRect(transformedBounds);
-
canvas.save();
- Matrix matrix = getLocalMatrix();
- canvas.translate((getWidth() - bitmap.getWidth()) / 2.0f,
- (getHeight() - bitmap.getHeight()) / 2.0f);
paint.setARGB(255, 0, 0, 0);
- Matrix drawMatrix = new Matrix();
- float w = bitmap.getWidth();
- drawMatrix.preScale(1.0f/w, 1.0f/w);
- drawMatrix.postConcat(matrix);
- drawMatrix.postScale(w, w);
- canvas.drawBitmap(bitmap, drawMatrix, paint);
+ drawImage(canvas, bitmap, paint);
canvas.restore();
-
canvas.save();
canvas.setMatrix(boundsMatrix);
paint.setColor(Color.WHITE);
canvas.restore();
if (!clip) { // we display the rest of the bitmap grayed-out
- drawShadows(canvas, transformedBounds, new RectF(0, 0, getWidth(), getHeight()), paint);
+ drawShadows(canvas, transformedBounds, new RectF(0, 0, w, h), paint);
}
}