diff options
Diffstat (limited to 'src/com/android/gallery3d/filtershow/filters/ImageFilterDraw.java')
-rw-r--r-- | src/com/android/gallery3d/filtershow/filters/ImageFilterDraw.java | 278 |
1 files changed, 278 insertions, 0 deletions
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..7df5ffb64 --- /dev/null +++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterDraw.java @@ -0,0 +1,278 @@ +/* + * 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.BitmapFactory; +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.PathMeasure; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; + +import com.android.gallery3d.R; +import com.android.gallery3d.filtershow.cache.ImageLoader; +import com.android.gallery3d.filtershow.filters.FilterDrawRepresentation.StrokeData; +import com.android.gallery3d.filtershow.imageshow.MasterImage; +import com.android.gallery3d.filtershow.pipeline.FilterEnvironment; + +import java.util.Vector; + +public class ImageFilterDraw extends ImageFilter { + private static final String LOGTAG = "ImageFilterDraw"; + public final static byte SIMPLE_STYLE = 0; + public final static byte BRUSH_STYLE_SPATTER = 1; + public final static byte BRUSH_STYLE_MARKER = 2; + public final static int NUMBER_OF_STYLES = 3; + Bitmap mOverlayBitmap; // this accelerates interaction + int mCachedStrokes = -1; + int mCurrentStyle = 0; + + FilterDrawRepresentation mParameters = new FilterDrawRepresentation(); + + public ImageFilterDraw() { + mName = "Image Draw"; + } + + DrawStyle[] mDrawingsTypes = new DrawStyle[] { + new SimpleDraw(), + new Brush(R.drawable.brush_marker), + new Brush(R.drawable.brush_spatter) + }; + { + for (int i = 0; i < mDrawingsTypes.length; i++) { + mDrawingsTypes[i].setType((byte) i); + } + + } + + @Override + public FilterRepresentation getDefaultRepresentation() { + return new FilterDrawRepresentation(); + } + + @Override + public void useRepresentation(FilterRepresentation representation) { + FilterDrawRepresentation parameters = (FilterDrawRepresentation) representation; + mParameters = parameters; + } + + public void setStyle(byte style) { + mCurrentStyle = style % mDrawingsTypes.length; + } + + public int getStyle() { + return mCurrentStyle; + } + + public static interface DrawStyle { + public void setType(byte type); + public void paint(FilterDrawRepresentation.StrokeData sd, Canvas canvas, Matrix toScrMatrix, + int quality); + } + + class SimpleDraw implements DrawStyle { + byte mType; + + @Override + public void setType(byte type) { + mType = type; + } + + @Override + public void paint(FilterDrawRepresentation.StrokeData sd, Canvas canvas, Matrix toScrMatrix, + int quality) { + if (sd == null) { + return; + } + if (sd.mPath == null) { + return; + } + Paint paint = new Paint(); + + paint.setStyle(Style.STROKE); + paint.setColor(sd.mColor); + paint.setStrokeWidth(toScrMatrix.mapRadius(sd.mRadius)); + + // done this way because of a bug in path.transform(matrix) + Path mCacheTransPath = new Path(); + mCacheTransPath.addPath(sd.mPath, toScrMatrix); + + canvas.drawPath(mCacheTransPath, paint); + } + } + + class Brush implements DrawStyle { + int mBrushID; + Bitmap mBrush; + byte mType; + + public Brush(int brushID) { + mBrushID = brushID; + } + + public Bitmap getBrush() { + if (mBrush == null) { + BitmapFactory.Options opt = new BitmapFactory.Options(); + opt.inPreferredConfig = Bitmap.Config.ALPHA_8; + mBrush = BitmapFactory.decodeResource(MasterImage.getImage().getActivity() + .getResources(), mBrushID, opt); + mBrush = mBrush.extractAlpha(); + } + return mBrush; + } + + @Override + public void paint(FilterDrawRepresentation.StrokeData sd, Canvas canvas, + Matrix toScrMatrix, + int quality) { + if (sd == null || sd.mPath == null) { + return; + } + Paint paint = new Paint(); + paint.setStyle(Style.STROKE); + paint.setAntiAlias(true); + Path mCacheTransPath = new Path(); + mCacheTransPath.addPath(sd.mPath, toScrMatrix); + draw(canvas, paint, sd.mColor, toScrMatrix.mapRadius(sd.mRadius) * 2, + mCacheTransPath); + } + + public Bitmap createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter) + { + Matrix m = new Matrix(); + m.setScale(dstWidth / (float) src.getWidth(), dstHeight / (float) src.getHeight()); + Bitmap result = Bitmap.createBitmap(dstWidth, dstHeight, src.getConfig()); + Canvas canvas = new Canvas(result); + + Paint paint = new Paint(); + paint.setFilterBitmap(filter); + canvas.drawBitmap(src, m, paint); + + return result; + + } + void draw(Canvas canvas, Paint paint, int color, float size, Path path) { + PathMeasure mPathMeasure = new PathMeasure(); + float[] mPosition = new float[2]; + float[] mTan = new float[2]; + + mPathMeasure.setPath(path, false); + + paint.setAntiAlias(true); + paint.setColor(color); + + paint.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)); + Bitmap brush; + // done this way because of a bug in + // Bitmap.createScaledBitmap(getBrush(),(int) size,(int) size,true); + brush = createScaledBitmap(getBrush(), (int) size, (int) size, true); + float len = mPathMeasure.getLength(); + float s2 = size / 2; + float step = s2 / 8; + for (float i = 0; i < len; i += step) { + mPathMeasure.getPosTan(i, mPosition, mTan); + // canvas.drawCircle(pos[0], pos[1], size, paint); + canvas.drawBitmap(brush, mPosition[0] - s2, mPosition[1] - s2, paint); + } + } + + @Override + public void setType(byte type) { + mType = type; + } + } + + void paint(FilterDrawRepresentation.StrokeData sd, Canvas canvas, Matrix toScrMatrix, + int quality) { + mDrawingsTypes[sd.mType].paint(sd, canvas, toScrMatrix, quality); + } + + public void drawData(Canvas canvas, Matrix originalRotateToScreen, int quality) { + Paint paint = new Paint(); + if (quality == FilterEnvironment.QUALITY_FINAL) { + paint.setAntiAlias(true); + } + paint.setStyle(Style.STROKE); + paint.setColor(Color.RED); + paint.setStrokeWidth(40); + + if (mParameters.getDrawing().isEmpty() && mParameters.getCurrentDrawing() == null) { + return; + } + if (quality == FilterEnvironment.QUALITY_FINAL) { + for (FilterDrawRepresentation.StrokeData strokeData : mParameters.getDrawing()) { + paint(strokeData, canvas, originalRotateToScreen, quality); + } + return; + } + + if (mOverlayBitmap == null || + mOverlayBitmap.getWidth() != canvas.getWidth() || + mOverlayBitmap.getHeight() != canvas.getHeight() || + mParameters.getDrawing().size() < mCachedStrokes) { + + mOverlayBitmap = Bitmap.createBitmap( + canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888); + mCachedStrokes = 0; + } + + if (mCachedStrokes < mParameters.getDrawing().size()) { + fillBuffer(originalRotateToScreen); + } + canvas.drawBitmap(mOverlayBitmap, 0, 0, paint); + + StrokeData stroke = mParameters.getCurrentDrawing(); + if (stroke != null) { + paint(stroke, canvas, originalRotateToScreen, quality); + } + } + + public void fillBuffer(Matrix originalRotateToScreen) { + Canvas drawCache = new Canvas(mOverlayBitmap); + Vector<FilterDrawRepresentation.StrokeData> v = mParameters.getDrawing(); + int n = v.size(); + + for (int i = mCachedStrokes; i < n; i++) { + paint(v.get(i), drawCache, originalRotateToScreen, FilterEnvironment.QUALITY_PREVIEW); + } + mCachedStrokes = n; + } + + public void draw(Canvas canvas, Matrix originalRotateToScreen) { + for (FilterDrawRepresentation.StrokeData strokeData : mParameters.getDrawing()) { + paint(strokeData, canvas, originalRotateToScreen, FilterEnvironment.QUALITY_PREVIEW); + } + mDrawingsTypes[mCurrentStyle].paint( + null, canvas, originalRotateToScreen, FilterEnvironment.QUALITY_PREVIEW); + } + + @Override + public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) { + int w = bitmap.getWidth(); + int h = bitmap.getHeight(); + + Matrix m = getOriginalToScreenMatrix(w, h); + drawData(new Canvas(bitmap), m, quality); + return bitmap; + } + +} |