diff options
Diffstat (limited to 'src/com/android/gallery3d/filtershow/imageshow/ImageStraighten.java')
-rw-r--r-- | src/com/android/gallery3d/filtershow/imageshow/ImageStraighten.java | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageStraighten.java b/src/com/android/gallery3d/filtershow/imageshow/ImageStraighten.java new file mode 100644 index 000000000..ff75dcc09 --- /dev/null +++ b/src/com/android/gallery3d/filtershow/imageshow/ImageStraighten.java @@ -0,0 +1,260 @@ +/* + * Copyright (C) 2012 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.gallery3d.filtershow.imageshow; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.Paint.Style; +import android.graphics.Path; +import android.graphics.RectF; +import android.util.AttributeSet; +import android.view.MotionEvent; + +import com.android.gallery3d.filtershow.editors.EditorStraighten; +import com.android.gallery3d.filtershow.filters.FilterCropRepresentation; +import com.android.gallery3d.filtershow.filters.FilterRepresentation; +import com.android.gallery3d.filtershow.filters.FilterStraightenRepresentation; +import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils.GeometryHolder; + +import java.util.ArrayList; +import java.util.Collection; + + +public class ImageStraighten extends ImageShow { + private static final String TAG = ImageStraighten.class.getSimpleName(); + private float mBaseAngle = 0; + private float mAngle = 0; + private float mInitialAngle = 0; + private boolean mFirstDrawSinceUp = false; + private EditorStraighten mEditorStraighten; + private FilterStraightenRepresentation mLocalRep = new FilterStraightenRepresentation(); + private RectF mPriorCropAtUp = new RectF(); + private RectF mDrawRect = new RectF(); + private Path mDrawPath = new Path(); + private GeometryHolder mDrawHolder = new GeometryHolder(); + private enum MODES { + NONE, MOVE + } + private MODES mState = MODES.NONE; + private static final float MAX_STRAIGHTEN_ANGLE + = FilterStraightenRepresentation.MAX_STRAIGHTEN_ANGLE; + private static final float MIN_STRAIGHTEN_ANGLE + = FilterStraightenRepresentation.MIN_STRAIGHTEN_ANGLE; + private float mCurrentX; + private float mCurrentY; + private float mTouchCenterX; + private float mTouchCenterY; + private RectF mCrop = new RectF(); + private final Paint mPaint = new Paint(); + + public ImageStraighten(Context context) { + super(context); + } + + public ImageStraighten(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public void setFilterStraightenRepresentation(FilterStraightenRepresentation rep) { + mLocalRep = (rep == null) ? new FilterStraightenRepresentation() : rep; + mInitialAngle = mBaseAngle = mAngle = mLocalRep.getStraighten(); + } + + public Collection<FilterRepresentation> getFinalRepresentation() { + ArrayList<FilterRepresentation> reps = new ArrayList<FilterRepresentation>(2); + reps.add(mLocalRep); + if (mInitialAngle != mLocalRep.getStraighten()) { + reps.add(new FilterCropRepresentation(mCrop)); + } + return reps; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + float x = event.getX(); + float y = event.getY(); + + switch (event.getActionMasked()) { + case (MotionEvent.ACTION_DOWN): + if (mState == MODES.NONE) { + mTouchCenterX = x; + mTouchCenterY = y; + mCurrentX = x; + mCurrentY = y; + mState = MODES.MOVE; + mBaseAngle = mAngle; + } + break; + case (MotionEvent.ACTION_UP): + if (mState == MODES.MOVE) { + mState = MODES.NONE; + mCurrentX = x; + mCurrentY = y; + computeValue(); + mFirstDrawSinceUp = true; + } + break; + case (MotionEvent.ACTION_MOVE): + if (mState == MODES.MOVE) { + mCurrentX = x; + mCurrentY = y; + computeValue(); + } + break; + default: + break; + } + invalidate(); + return true; + } + + private static float angleFor(float dx, float dy) { + return (float) (Math.atan2(dx, dy) * 180 / Math.PI); + } + + private float getCurrentTouchAngle() { + float centerX = getWidth() / 2f; + float centerY = getHeight() / 2f; + if (mCurrentX == mTouchCenterX && mCurrentY == mTouchCenterY) { + return 0; + } + float dX1 = mTouchCenterX - centerX; + float dY1 = mTouchCenterY - centerY; + float dX2 = mCurrentX - centerX; + float dY2 = mCurrentY - centerY; + float angleA = angleFor(dX1, dY1); + float angleB = angleFor(dX2, dY2); + return (angleB - angleA) % 360; + } + + private void computeValue() { + float angle = getCurrentTouchAngle(); + mAngle = (mBaseAngle - angle) % 360; + mAngle = Math.max(MIN_STRAIGHTEN_ANGLE, mAngle); + mAngle = Math.min(MAX_STRAIGHTEN_ANGLE, mAngle); + } + + private static void getUntranslatedStraightenCropBounds(RectF outRect, float straightenAngle) { + float deg = straightenAngle; + if (deg < 0) { + deg = -deg; + } + double a = Math.toRadians(deg); + double sina = Math.sin(a); + double cosa = Math.cos(a); + double rw = outRect.width(); + double rh = outRect.height(); + double h1 = rh * rh / (rw * sina + rh * cosa); + double h2 = rh * rw / (rw * cosa + rh * sina); + double hh = Math.min(h1, h2); + double ww = hh * rw / rh; + float left = (float) ((rw - ww) * 0.5f); + float top = (float) ((rh - hh) * 0.5f); + float right = (float) (left + ww); + float bottom = (float) (top + hh); + outRect.set(left, top, right, bottom); + } + + private void updateCurrentCrop(Matrix m, GeometryHolder h, RectF tmp, int imageWidth, + int imageHeight, int viewWidth, int viewHeight) { + if (GeometryMathUtils.needsDimensionSwap(h.rotation)) { + tmp.set(0, 0, imageHeight, imageWidth); + } else { + tmp.set(0, 0, imageWidth, imageHeight); + } + float scale = GeometryMathUtils.scale(imageWidth, imageHeight, viewWidth, viewHeight); + GeometryMathUtils.scaleRect(tmp, scale); + getUntranslatedStraightenCropBounds(tmp, mAngle); + tmp.offset(viewWidth / 2f - tmp.centerX(), viewHeight / 2f - tmp.centerY()); + h.straighten = 0; + Matrix m1 = GeometryMathUtils.getFullGeometryToScreenMatrix(h, imageWidth, + imageHeight, viewWidth, viewHeight); + m.reset(); + m1.invert(m); + mCrop.set(tmp); + m.mapRect(mCrop); + FilterCropRepresentation.findNormalizedCrop(mCrop, imageWidth, imageHeight); + } + + + @Override + public void onDraw(Canvas canvas) { + MasterImage master = MasterImage.getImage(); + Bitmap image = master.getFiltersOnlyImage(); + if (image == null) { + return; + } + GeometryMathUtils.initializeHolder(mDrawHolder, mLocalRep); + mDrawHolder.straighten = mAngle; + int imageWidth = image.getWidth(); + int imageHeight = image.getHeight(); + int viewWidth = canvas.getWidth(); + int viewHeight = canvas.getHeight(); + + // Get matrix for drawing bitmap + Matrix m = GeometryMathUtils.getFullGeometryToScreenMatrix(mDrawHolder, imageWidth, + imageHeight, viewWidth, viewHeight); + mPaint.reset(); + mPaint.setAntiAlias(true); + mPaint.setFilterBitmap(true); + canvas.drawBitmap(image, m, mPaint); + + mPaint.setFilterBitmap(false); + mPaint.setColor(Color.WHITE); + mPaint.setStrokeWidth(2); + mPaint.setStyle(Paint.Style.FILL_AND_STROKE); + updateCurrentCrop(m, mDrawHolder, mDrawRect, imageWidth, + imageHeight, viewWidth, viewHeight); + if (mFirstDrawSinceUp) { + mPriorCropAtUp.set(mCrop); + mLocalRep.setStraighten(mAngle); + mFirstDrawSinceUp = false; + } + + // Draw the grid + if (mState == MODES.MOVE) { + canvas.save(); + canvas.clipRect(mDrawRect); + int n = 16; + float step = viewWidth / n; + float p = 0; + for (int i = 1; i < n; i++) { + p = i * step; + mPaint.setAlpha(60); + canvas.drawLine(p, 0, p, viewHeight, mPaint); + canvas.drawLine(0, p, viewHeight, p, mPaint); + } + canvas.restore(); + } + mPaint.reset(); + mPaint.setColor(Color.WHITE); + mPaint.setStyle(Style.STROKE); + mPaint.setStrokeWidth(3); + mDrawPath.reset(); + mDrawPath.addRect(mDrawRect, Path.Direction.CW); + canvas.drawPath(mDrawPath, mPaint); + } + + public void setEditor(EditorStraighten editorStraighten) { + mEditorStraighten = editorStraighten; + } + +} |