• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.gallery3d.filtershow.filters;
18 
19 import android.graphics.Bitmap;
20 import android.graphics.BitmapFactory;
21 import android.graphics.Canvas;
22 import android.graphics.Color;
23 import android.graphics.Matrix;
24 import android.graphics.Paint;
25 import android.graphics.Paint.Style;
26 import android.graphics.Path;
27 import android.graphics.PathMeasure;
28 import android.graphics.PorterDuff;
29 import android.graphics.PorterDuffColorFilter;
30 
31 import com.android.gallery3d.R;
32 import com.android.gallery3d.filtershow.filters.FilterDrawRepresentation.StrokeData;
33 import com.android.gallery3d.filtershow.imageshow.MasterImage;
34 import com.android.gallery3d.filtershow.presets.ImagePreset;
35 
36 import java.util.Vector;
37 
38 public class ImageFilterDraw extends ImageFilter {
39     private static final String LOGTAG = "ImageFilterDraw";
40     public final static byte SIMPLE_STYLE = 0;
41     public final static byte BRUSH_STYLE_SPATTER = 1;
42     public final static byte BRUSH_STYLE_MARKER = 2;
43     public final static int NUMBER_OF_STYLES = 3;
44     Bitmap mOverlayBitmap; // this accelerates interaction
45     int mCachedStrokes = -1;
46     int mCurrentStyle = 0;
47 
48     FilterDrawRepresentation mParameters = new FilterDrawRepresentation();
49 
ImageFilterDraw()50     public ImageFilterDraw() {
51         mName = "Image Draw";
52     }
53 
54     DrawStyle[] mDrawingsTypes = new DrawStyle[] {
55             new SimpleDraw(),
56             new Brush(R.drawable.brush_marker),
57             new Brush(R.drawable.brush_spatter)
58     };
59     {
60         for (int i = 0; i < mDrawingsTypes.length; i++) {
61             mDrawingsTypes[i].setType((byte) i);
62         }
63 
64     }
65 
66     @Override
getDefaultRepresentation()67     public FilterRepresentation getDefaultRepresentation() {
68         return new FilterDrawRepresentation();
69     }
70 
71     @Override
useRepresentation(FilterRepresentation representation)72     public void useRepresentation(FilterRepresentation representation) {
73         FilterDrawRepresentation parameters = (FilterDrawRepresentation) representation;
74         mParameters = parameters;
75     }
76 
setStyle(byte style)77     public void setStyle(byte style) {
78         mCurrentStyle = style % mDrawingsTypes.length;
79     }
80 
getStyle()81     public int getStyle() {
82         return mCurrentStyle;
83     }
84 
85     public static interface DrawStyle {
setType(byte type)86         public void setType(byte type);
paint(FilterDrawRepresentation.StrokeData sd, Canvas canvas, Matrix toScrMatrix, int quality)87         public void paint(FilterDrawRepresentation.StrokeData sd, Canvas canvas, Matrix toScrMatrix,
88                 int quality);
89     }
90 
91     class SimpleDraw implements DrawStyle {
92         byte mType;
93 
94         @Override
setType(byte type)95         public void setType(byte type) {
96             mType = type;
97         }
98 
99         @Override
paint(FilterDrawRepresentation.StrokeData sd, Canvas canvas, Matrix toScrMatrix, int quality)100         public void paint(FilterDrawRepresentation.StrokeData sd, Canvas canvas, Matrix toScrMatrix,
101                 int quality) {
102             if (sd == null) {
103                 return;
104             }
105             if (sd.mPath == null) {
106                 return;
107             }
108             Paint paint = new Paint();
109 
110             paint.setStyle(Style.STROKE);
111             paint.setColor(sd.mColor);
112             paint.setStrokeWidth(toScrMatrix.mapRadius(sd.mRadius));
113 
114             // done this way because of a bug in path.transform(matrix)
115             Path mCacheTransPath = new Path();
116             mCacheTransPath.addPath(sd.mPath, toScrMatrix);
117 
118             canvas.drawPath(mCacheTransPath, paint);
119         }
120     }
121 
122     class Brush implements DrawStyle {
123         int mBrushID;
124         Bitmap mBrush;
125         byte mType;
126 
Brush(int brushID)127         public Brush(int brushID) {
128             mBrushID = brushID;
129         }
getBrush()130         public Bitmap getBrush() {
131             if (mBrush == null) {
132                 BitmapFactory.Options opt = new BitmapFactory.Options();
133                 opt.inPreferredConfig = Bitmap.Config.ALPHA_8;
134                 mBrush = MasterImage.getImage().getImageLoader().decodeImage(mBrushID, opt);
135                 mBrush = mBrush.extractAlpha();
136             }
137             return mBrush;
138         }
139 
140         @Override
paint(FilterDrawRepresentation.StrokeData sd, Canvas canvas, Matrix toScrMatrix, int quality)141         public void paint(FilterDrawRepresentation.StrokeData sd, Canvas canvas, Matrix toScrMatrix,
142                 int quality) {
143             if (sd == null || sd.mPath == null) {
144                 return;
145             }
146             Paint paint = new Paint();
147             paint.setStyle(Style.STROKE);
148             paint.setAntiAlias(true);
149             Path mCacheTransPath = new Path();
150             mCacheTransPath.addPath(sd.mPath, toScrMatrix);
151             draw(canvas, paint, sd.mColor, toScrMatrix.mapRadius(sd.mRadius) * 2,
152                     mCacheTransPath);
153         }
154 
createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter)155         public Bitmap createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter)
156         {
157             Matrix m = new Matrix();
158             m.setScale(dstWidth / (float) src.getWidth(), dstHeight / (float) src.getHeight());
159             Bitmap result = Bitmap.createBitmap(dstWidth, dstHeight, src.getConfig());
160             Canvas canvas = new Canvas(result);
161 
162             Paint paint = new Paint();
163             paint.setFilterBitmap(filter);
164             canvas.drawBitmap(src, m, paint);
165 
166             return result;
167 
168         }
draw(Canvas canvas, Paint paint, int color, float size, Path path)169         void draw(Canvas canvas, Paint paint, int color, float size, Path path) {
170             PathMeasure mPathMeasure = new PathMeasure();
171             float[] mPosition = new float[2];
172             float[] mTan = new float[2];
173 
174             mPathMeasure.setPath(path, false);
175 
176             paint.setAntiAlias(true);
177             paint.setColor(color);
178 
179             paint.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY));
180             Bitmap brush;
181             // done this way because of a bug in
182             // Bitmap.createScaledBitmap(getBrush(),(int) size,(int) size,true);
183             brush = createScaledBitmap(getBrush(), (int) size, (int) size, true);
184             float len = mPathMeasure.getLength();
185             float s2 = size / 2;
186             float step = s2 / 8;
187             for (float i = 0; i < len; i += step) {
188                 mPathMeasure.getPosTan(i, mPosition, mTan);
189                 //                canvas.drawCircle(pos[0], pos[1], size, paint);
190                 canvas.drawBitmap(brush, mPosition[0] - s2, mPosition[1] - s2, paint);
191             }
192         }
193 
194         @Override
setType(byte type)195         public void setType(byte type) {
196             mType = type;
197         }
198     }
199 
paint(FilterDrawRepresentation.StrokeData sd, Canvas canvas, Matrix toScrMatrix, int quality)200     void paint(FilterDrawRepresentation.StrokeData sd, Canvas canvas, Matrix toScrMatrix,
201             int quality) {
202         mDrawingsTypes[sd.mType].paint(sd, canvas, toScrMatrix, quality);
203     }
204 
drawData(Canvas canvas, Matrix originalRotateToScreen, int quality)205     public void drawData(Canvas canvas, Matrix originalRotateToScreen, int quality) {
206         Paint paint = new Paint();
207         if (quality == ImagePreset.QUALITY_FINAL) {
208             paint.setAntiAlias(true);
209         }
210         paint.setStyle(Style.STROKE);
211         paint.setColor(Color.RED);
212         paint.setStrokeWidth(40);
213 
214         if (mParameters.getDrawing().isEmpty() && mParameters.getCurrentDrawing() == null) {
215             return;
216         }
217         if (quality == ImagePreset.QUALITY_FINAL) {
218             for (FilterDrawRepresentation.StrokeData strokeData : mParameters.getDrawing()) {
219                 paint(strokeData, canvas, originalRotateToScreen, quality);
220             }
221             return;
222         }
223 
224         if (mOverlayBitmap == null ||
225                 mOverlayBitmap.getWidth() != canvas.getWidth() ||
226                 mOverlayBitmap.getHeight() != canvas.getHeight() ||
227                 mParameters.getDrawing().size() < mCachedStrokes) {
228 
229             mOverlayBitmap = Bitmap.createBitmap(
230                     canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888);
231             mCachedStrokes = 0;
232         }
233 
234         if (mCachedStrokes < mParameters.getDrawing().size()) {
235             fillBuffer(originalRotateToScreen);
236         }
237         canvas.drawBitmap(mOverlayBitmap, 0, 0, paint);
238 
239         StrokeData stroke = mParameters.getCurrentDrawing();
240         if (stroke != null) {
241             paint(stroke, canvas, originalRotateToScreen, quality);
242         }
243     }
244 
fillBuffer(Matrix originalRotateToScreen)245     public void fillBuffer(Matrix originalRotateToScreen) {
246         Canvas drawCache = new Canvas(mOverlayBitmap);
247         Vector<FilterDrawRepresentation.StrokeData> v = mParameters.getDrawing();
248         int n = v.size();
249 
250         for (int i = mCachedStrokes; i < n; i++) {
251             paint(v.get(i), drawCache, originalRotateToScreen, ImagePreset.QUALITY_PREVIEW);
252         }
253         mCachedStrokes = n;
254     }
255 
draw(Canvas canvas, Matrix originalRotateToScreen)256     public void draw(Canvas canvas, Matrix originalRotateToScreen) {
257         for (FilterDrawRepresentation.StrokeData strokeData : mParameters.getDrawing()) {
258             paint(strokeData, canvas, originalRotateToScreen, ImagePreset.QUALITY_PREVIEW);
259         }
260         mDrawingsTypes[mCurrentStyle].paint(
261                 null, canvas, originalRotateToScreen, ImagePreset.QUALITY_PREVIEW);
262     }
263 
264     @Override
apply(Bitmap bitmap, float scaleFactor, int quality)265     public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
266         int w = bitmap.getWidth();
267         int h = bitmap.getHeight();
268 
269         Matrix m = getOriginalToScreenMatrix(w, h);
270         drawData(new Canvas(bitmap), m, quality);
271         return bitmap;
272     }
273 
274 }
275