diff options
author | John Hoford <hoford@google.com> | 2013-01-08 14:20:58 -0800 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2013-01-08 14:20:59 -0800 |
commit | 534fc631c98d51b186b823608a0d9e267b3c0ea8 (patch) | |
tree | 7e4f2816097f8439a5cda813f29e2e6fc59ce5da /src/com/android/gallery3d/filtershow | |
parent | a91969297aac4fa4572ad7c69d4d5924ce4b8de2 (diff) | |
parent | 7b9803262e5f1ebb9464d5cf857f9cbb38f888bf (diff) | |
download | android_packages_apps_Snap-534fc631c98d51b186b823608a0d9e267b3c0ea8.tar.gz android_packages_apps_Snap-534fc631c98d51b186b823608a0d9e267b3c0ea8.tar.bz2 android_packages_apps_Snap-534fc631c98d51b186b823608a0d9e267b3c0ea8.zip |
Merge "Add a Draw filter" into gb-ub-photos-bryce
Diffstat (limited to 'src/com/android/gallery3d/filtershow')
3 files changed, 430 insertions, 0 deletions
diff --git a/src/com/android/gallery3d/filtershow/FilterShowActivity.java b/src/com/android/gallery3d/filtershow/FilterShowActivity.java index bc90a31ba..755bd8031 100644 --- a/src/com/android/gallery3d/filtershow/FilterShowActivity.java +++ b/src/com/android/gallery3d/filtershow/FilterShowActivity.java @@ -62,6 +62,7 @@ import com.android.gallery3d.filtershow.filters.ImageFilterBwFilter; import com.android.gallery3d.filtershow.filters.ImageFilterContrast; import com.android.gallery3d.filtershow.filters.ImageFilterCurves; import com.android.gallery3d.filtershow.filters.ImageFilterDownsample; +import com.android.gallery3d.filtershow.filters.ImageFilterDraw; import com.android.gallery3d.filtershow.filters.ImageFilterEdge; import com.android.gallery3d.filtershow.filters.ImageFilterExposure; import com.android.gallery3d.filtershow.filters.ImageFilterFx; @@ -80,6 +81,7 @@ import com.android.gallery3d.filtershow.filters.ImageFilterVignette; import com.android.gallery3d.filtershow.filters.ImageFilterWBalance; import com.android.gallery3d.filtershow.imageshow.ImageBorder; import com.android.gallery3d.filtershow.imageshow.ImageCrop; +import com.android.gallery3d.filtershow.imageshow.ImageDraw; import com.android.gallery3d.filtershow.imageshow.ImageFlip; import com.android.gallery3d.filtershow.imageshow.ImageRedEyes; import com.android.gallery3d.filtershow.imageshow.ImageRotate; @@ -120,6 +122,7 @@ public class FilterShowActivity extends Activity implements OnItemClickListener, private ImageCurves mImageCurves = null; private ImageBorder mImageBorders = null; private ImageRedEyes mImageRedEyes = null; + private ImageDraw mImageDraw = null; private ImageStraighten mImageStraighten = null; private ImageZoom mImageZoom = null; private ImageCrop mImageCrop = null; @@ -221,6 +224,7 @@ public class FilterShowActivity extends Activity implements OnItemClickListener, mImageFlip = (ImageFlip) findViewById(R.id.imageFlip); mImageTinyPlanet = (ImageTinyPlanet) findViewById(R.id.imageTinyPlanet); mImageRedEyes = (ImageRedEyes) findViewById(R.id.imageRedEyes); + mImageDraw = (ImageDraw) findViewById(R.id.imageDraw); mImageCrop.setAspectTextSize((int) getPixelsFromDip(18)); ImageCrop.setTouchTolerance((int) getPixelsFromDip(25)); @@ -280,6 +284,9 @@ public class FilterShowActivity extends Activity implements OnItemClickListener, mImageRedEyes.setImageLoader(mImageLoader); mImageRedEyes.setMaster(mImageShow); + mImageDraw.setImageLoader(mImageLoader); + mImageDraw.setMaster(mImageShow); + mPanelController.setActivity(this); mPanelController.addImageView(findViewById(R.id.imageShow)); @@ -292,6 +299,7 @@ public class FilterShowActivity extends Activity implements OnItemClickListener, mPanelController.addImageView(findViewById(R.id.imageZoom)); mPanelController.addImageView(findViewById(R.id.imageTinyPlanet)); mPanelController.addImageView(findViewById(R.id.imageRedEyes)); + mPanelController.addImageView(findViewById(R.id.imageDraw)); mPanelController.addPanel(mFxButton, mListFx, 0); mPanelController.addPanel(mBorderButton, mListBorders, 1); @@ -315,6 +323,7 @@ public class FilterShowActivity extends Activity implements OnItemClickListener, new ImageFilterVibrance(), new ImageFilterSharpen(), new ImageFilterCurves(), + new ImageFilterDraw(), new ImageFilterHue(), new ImageFilterSaturated(), new ImageFilterBwFilter(), diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterDraw.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterDraw.java new file mode 100644 index 000000000..cadcbb3f9 --- /dev/null +++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterDraw.java @@ -0,0 +1,302 @@ +/* + * 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.filters; + +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.graphics.RectF; +import android.graphics.Xfermode; +import android.graphics.Paint.Style; +import android.util.Log; + +import com.android.gallery3d.R; +import com.android.gallery3d.filtershow.imageshow.GeometryMetadata; + +import java.util.Arrays; +import java.util.Vector; + +public class ImageFilterDraw extends ImageFilter { + private static final String LOGTAG = "ImageFilterDraw"; + + final float STROKE_RADIUS = 40; + Bitmap mOverlayBitmap; // this accelerates interaction + int mCachedStrokes =-1; + SimpleDraw mSimpleDraw = new SimpleDraw(); + + public static interface DrawStyle { + public DrawStyle clone(); + public void setSize(float radius); + public void setColor(int color); + public void startStroke(float x, float y); + public void stroke(float x, float y); + public void endStroke(float x, float y); + public int getNumberOfStrokes(); + public void clearCurren(); + public void paintCurrentStroke(Canvas canvas, Matrix toScrMatrix, boolean highQuality); + public int paintLast(int from, Canvas canvas, Matrix toScrMatrix, boolean highQuality); + public boolean same(DrawStyle o); + }; + + class SimpleDraw implements DrawStyle { + private Path[] mPaths = new Path[0]; + private int[] mColors = new int[0]; + private float[] mRadius = new float[0]; + private int mStrokeCnt = 0; + + private Path mCurrentPath; + private float mCurrentRadius; + private int mCurrentColor; + + public DrawStyle clone() { + SimpleDraw ret = new SimpleDraw(); + ret.mPaths = new Path[mPaths.length]; + for (int i = 0; i < mPaths.length; i++) { + ret.mPaths[i] = new Path(mPaths[i]); + } + ret.mColors = Arrays.copyOf(mColors, mColors.length); + ret.mRadius = Arrays.copyOf(mRadius, mRadius.length); + ret.mStrokeCnt = mStrokeCnt; + return ret; + } + + public void setSize(float radius) { + mCurrentRadius = radius; + } + + public void setColor(int color) { + mCurrentColor = color; + } + + public void startStroke(float x, float y) { + mCurrentPath = new Path(); + mCurrentPath.moveTo(x, y); + } + + public void stroke(float x, float y) { + if (mCurrentPath != null) { + mCurrentPath.lineTo(x, y); + } + } + + public void endStroke(float x, float y) { + if (mCurrentPath != null) { + mCurrentPath.lineTo(x, y); + Path[] np = new Path[mStrokeCnt + 1]; + for (int i = 0; i < mStrokeCnt; i++) { + np[i] = mPaths[i]; + } + np[mStrokeCnt] = mCurrentPath; + mColors = Arrays.copyOf(mColors, mColors.length + 1); + mRadius = Arrays.copyOf(mRadius, mRadius.length + 1); + mRadius[mStrokeCnt] = mCurrentRadius; + mColors[mStrokeCnt] = mCurrentColor; + mPaths = np; + mStrokeCnt++; + } + } + public void clearCurren(){ + mCurrentPath = null; + } + public void paintCurrentStroke(Canvas canvas, Matrix toScrMatrix, boolean highQuality) { + Path path = mCurrentPath; + if (path == null) + return; + Paint paint = new Paint(); + + paint.setStyle(Style.STROKE); + paint.setColor(mCurrentColor); + paint.setStrokeWidth(toScrMatrix.mapRadius(mCurrentRadius)); + + // don this way because a bug in path.transform(matrix) + Path mCacheTransPath = new Path(); + mCacheTransPath.addPath(path, toScrMatrix); + + canvas.drawPath(mCacheTransPath, paint); + } + + public int paintLast(int from, Canvas canvas, Matrix toScrMatrix, boolean highQuality) { + Paint paint = new Paint(); + Matrix m = new Matrix(); + canvas.save(); + canvas.concat(toScrMatrix); + paint.setStyle(Style.STROKE); + for (int i = from; i < mStrokeCnt; i++) { + paint.setColor(mColors[i]); + paint.setStrokeWidth(mRadius[i]); + canvas.drawPath(mPaths[i], paint); + } + canvas.restore(); + return mStrokeCnt; + } + + public boolean same(DrawStyle o) { + if (!(o instanceof SimpleDraw)) { + return false; + } + SimpleDraw sd = (SimpleDraw) o; + boolean same; + same = Arrays.equals(mRadius, sd.mRadius); + if (!same) { + return false; + } + same = Arrays.equals(mColors, sd.mColors); + if (!same) { + return false; + } + for (int i = 0; i < mPaths.length; i++) { + if (!mPaths[i].equals(sd.mPaths)) { + return false; + } + } + return true; + } + + public int getNumberOfStrokes() { + return mStrokeCnt; + } + } + + public void startSection(int color, float x, float y) { + mSimpleDraw.setColor(color); + mSimpleDraw.setSize(STROKE_RADIUS); + mSimpleDraw.startStroke(x, y); + } + + public void addPoint(float x, float y) { + mSimpleDraw.stroke(x, y); + } + + public void endSection(float x, float y) { + mSimpleDraw.endStroke(x, y); + } + + public ImageFilterDraw() { + mName = "Image Draw"; + } + + public void drawData(Canvas canvas, Matrix originalRotateToScreen, boolean highQuality) { + Paint paint = new Paint(); + if (highQuality) { + paint.setAntiAlias(true); + } + paint.setStyle(Style.STROKE); + paint.setColor(Color.RED); + paint.setStrokeWidth(40); + if (mSimpleDraw.mStrokeCnt == -1) { + return; + } + if (highQuality) { + mSimpleDraw.paintLast(0, canvas, originalRotateToScreen, highQuality); + return; + } + if (mOverlayBitmap == null || + mOverlayBitmap.getWidth() != canvas.getWidth() || + mOverlayBitmap.getHeight() != canvas.getHeight()) { + + mOverlayBitmap = Bitmap.createBitmap( + canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888); + mCachedStrokes = 0; + } + if (mCachedStrokes < mSimpleDraw.getNumberOfStrokes()) { + fillBuffer(originalRotateToScreen); + } + canvas.drawBitmap(mOverlayBitmap, 0, 0, paint); + } + + public void fillBuffer(Matrix originalRotateToScreen) { + Paint paint = new Paint(); + paint.setStyle(Style.STROKE); + paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER)); + paint.setStrokeWidth(STROKE_RADIUS); + + Canvas drawCache = new Canvas(mOverlayBitmap); + mCachedStrokes = mSimpleDraw.paintLast( + mCachedStrokes, drawCache, originalRotateToScreen, false); + + } + + @Override + public int getButtonId() { + return R.id.drawOnImageButton; + } + + @Override + public int getTextId() { + return R.string.imageDraw; + } + + @Override + public int getEditingViewId() { + return R.id.imageDraw; + } + + @Override + public ImageFilter clone() throws CloneNotSupportedException { + ImageFilterDraw filter = (ImageFilterDraw) super.clone(); + + filter.mSimpleDraw = (SimpleDraw) mSimpleDraw.clone(); + return filter; + } + + @Override + public boolean isNil() { + if (mSimpleDraw.getNumberOfStrokes() != 0) { + return false; + } + return true; + } + + @Override + public boolean same(ImageFilter filter) { + boolean isSuperSame = super.same(filter); + if (!isSuperSame || !(filter instanceof ImageFilterDraw)) { + return false; + } + + ImageFilterDraw dfilter = (ImageFilterDraw) filter; + return mSimpleDraw.same(dfilter.mSimpleDraw); + } + + public void clear() { + mSimpleDraw.clearCurren(); + } + + public void draw(Canvas canvas, Matrix originalRotateToScreen) { + mSimpleDraw.paintCurrentStroke(canvas, originalRotateToScreen, false); + } + + @Override + public Bitmap apply(Bitmap bitmap, float scaleFactor, boolean highQuality) { + int w = bitmap.getWidth(); + int h = bitmap.getHeight(); + short[] rect = new short[4]; + + Matrix m = new Matrix(); + m.setScale(scaleFactor, scaleFactor); + + drawData(new Canvas(bitmap), m, highQuality); + + return bitmap; + } + +} diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageDraw.java b/src/com/android/gallery3d/filtershow/imageshow/ImageDraw.java new file mode 100644 index 000000000..b43cc1d4f --- /dev/null +++ b/src/com/android/gallery3d/filtershow/imageshow/ImageDraw.java @@ -0,0 +1,119 @@ + +package com.android.gallery3d.filtershow.imageshow; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.Paint.Style; +import android.graphics.RectF; +import android.util.AttributeSet; +import android.util.Log; +import android.view.MotionEvent; + +import com.android.gallery3d.filtershow.filters.ImageFilterDraw; +import com.android.gallery3d.filtershow.filters.RedEyeCandidate; + +public class ImageDraw extends ImageSlave { + + private static final String LOGTAG = "ImageDraw"; + + public ImageDraw(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public ImageDraw(Context context) { + super(context); + } + + @Override + public void resetParameter() { + ImageFilterDraw filter = (ImageFilterDraw) getCurrentFilter(); + if (filter != null) { + filter.clear(); + } + + invalidate(); + } + + @Override + public void updateImage() { + super.updateImage(); + invalidate(); + } + + float[] mTmpPoint = new float[2]; // so we do not malloc + @Override + public boolean onTouchEvent(MotionEvent event) { + super.onTouchEvent(event); + if (event.getPointerCount() != 1) { + return false; + } + + ImageFilterDraw filter = (ImageFilterDraw) getCurrentFilter(); + + if (event.getAction() == MotionEvent.ACTION_DOWN) { + + mTmpPoint[0] = event.getX(); + mTmpPoint[1] = event.getY(); + mToOrig.mapPoints(mTmpPoint); + float[] hsv = new float[3]; + hsv[0] = (float) (360 * Math.random()); + hsv[1] = 1; + hsv[2] = 1; + int col = Color.HSVToColor(0x88, hsv); + filter.startSection(col, mTmpPoint[0], mTmpPoint[1]); + + } + if (event.getAction() == MotionEvent.ACTION_MOVE) { + int historySize = event.getHistorySize(); + final int pointerCount = event.getPointerCount(); + for (int h = 0; h < historySize; h++) { + int p = 0; + { + mTmpPoint[0] = event.getHistoricalX(p, h); + mTmpPoint[1] = event.getHistoricalY(p, h); + mToOrig.mapPoints(mTmpPoint); + filter.addPoint(mTmpPoint[0], mTmpPoint[1]); + } + } + } + if (event.getAction() == MotionEvent.ACTION_UP) { + mTmpPoint[0] = event.getX(); + mTmpPoint[1] = event.getY(); + mToOrig.mapPoints(mTmpPoint); + filter.endSection(mTmpPoint[0], mTmpPoint[1]); + this.resetImageCaches(this); + + } + invalidate(); + return true; + } + + Matrix mRotateToScreen; + Matrix mToScreen; + Matrix mToOrig = new Matrix(); + private void calcScreenMapping() { + + GeometryMetadata geo = getImagePreset().mGeoData; + mToScreen = geo.getOriginalToScreen(false, + mImageLoader.getOriginalBounds().width(), + mImageLoader.getOriginalBounds().height(), getWidth(), getHeight()); + mRotateToScreen = geo.getOriginalToScreen(true, + mImageLoader.getOriginalBounds().width(), + mImageLoader.getOriginalBounds().height(), getWidth(), getHeight()); + mRotateToScreen.invert(mToOrig); + mToOrig.invert(mRotateToScreen); + } + + @Override + public void onDraw(Canvas canvas) { + super.onDraw(canvas); + + calcScreenMapping(); + + ImageFilterDraw filter = (ImageFilterDraw) getCurrentFilter(); + filter.draw(canvas, mRotateToScreen); + } +} |