博客分类:
http://stackoverflow.com/questions/3467334/erase-bitmap-parts-using-porterduff-mode
假如我有一张背景图片,
在背景图片上覆盖绘制了一层半透明的绿色
当我们用手指涂抹屏幕的时候,手指涂抹过的地方绿色就被擦除,露出下面原先被遮挡住的背景图片
1.利用canvas的drawPath做擦除效果。
效果如下:
实现代码:
1 import android.app.Activity;
2 import android.content.Context;
3 import android.graphics.Bitmap;
4 import android.graphics.BitmapFactory;
5 import android.graphics.Canvas;
6 import android.graphics.Paint;
7 import android.graphics.Path;
8 import android.graphics.PorterDuff;
9 import android.graphics.PorterDuffXfermode;
10 import android.graphics.Bitmap.Config;
11 import android.os.Bundle;
12 import android.util.DisplayMetrics;
13 import android.view.MotionEvent;
14 import android.view.View;
15
16 public class Eraser_Use_drawPath extends Activity {
17
18 private int SCREEN_W;
19
20 private int SCREEN_H;
21
22 @Override
23 protected void onCreate(Bundle savedInstanceState) {
24 super.onCreate(savedInstanceState);
25 setContentView(new MyView(this));
26
27 }
28
29 class MyView extends View {
30 private Bitmap mBitmap;
31 private Canvas mCanvas;
32 private Paint mPaint;
33 private Path mPath;
34 private float mX, mY;
35 private static final float TOUCH_TOLERANCE = 4;
36
37 public MyView(Context context) {
38 super(context);
39 setFocusable(true);
40 setScreenWH();
41 setBackGround();
42
43 // 1.if cover is a image,you can open MENU_ITEM_COMMENT bellow
44 //Bitmap bm = createBitmapFromSRC();
45 // if you want to set cover image's alpha,you can open MENU_ITEM_COMMENT bellow
46 //bm = setBitmapAlpha(bm, 100);
47 // if you want to scale cover image,you can open MENU_ITEM_COMMENT bellow
48 //bm = scaleBitmapFillScreen(bm);
49
50 // 2.if cover is color
51 Bitmap bm = createBitmapFromARGB(0x8800ff00, SCREEN_W, SCREEN_H);
52 setCoverBitmap(bm);
53
54 }
55
56 private void setScreenWH() {
57 // get screen info
58 DisplayMetrics dm = new DisplayMetrics();
59 dm = this.getResources().getDisplayMetrics();
60 // get screen width
61 int screenWidth = dm.widthPixels;
62 // get screen height
63 int screenHeight = dm.heightPixels;
64
65 SCREEN_W = screenWidth;
66 SCREEN_H = screenHeight;
67 }
68
69 private Bitmap createBitmapFromSRC() {
70 return BitmapFactory.decodeResource(getResources(),
71 R.drawable.cover);
72 }
73
74 /**
75 *
76 * @param colorARGB should like 0x8800ff00
77 * @param width
78 * @param height
79 * @return
80 */
81 private Bitmap createBitmapFromARGB(int colorARGB, int width, int height) {
82 int[] argb = new int[width * height];
83
84 for (int i = 0; i < argb.length; i++) {
85
86 argb[i] = colorARGB;
87
88 }
89 return Bitmap.createBitmap(argb, width, height, Config.ARGB_8888);
90 }
91
92 /**
93 *
94 * @param bm
95 * @param alpha ,and alpha should be like ox00000000-oxff000000
96 * @note set bitmap's alpha
97 * @return
98 */
99 /* private Bitmap setBitmapAlpha(Bitmap bm, int alpha) {
100 int[] argb = new int[bm.getWidth() * bm.getHeight()];
101 bm.getPixels(argb, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm
102 .getHeight());
103
104
105 for (int i = 0; i < argb.length; i++) {
106
107 argb[i] = ((alpha) | (argb[i] & 0x00FFFFFF));
108 }
109 return Bitmap.createBitmap(argb, bm.getWidth(), bm.getHeight(),
110 Config.ARGB_8888);
111 }*/
112
113 /**
114 *
115 * @param bm
116 * @param alpha ,alpha should be between 0 and 255
117 * @note set bitmap's alpha
118 * @return
119 */
120 private Bitmap setBitmapAlpha(Bitmap bm, int alpha) {
121 int[] argb = new int[bm.getWidth() * bm.getHeight()];
122 bm.getPixels(argb, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm
123 .getHeight());
124
125 for (int i = 0; i < argb.length; i++) {
126
127 argb[i] = ((alpha << 24) | (argb[i] & 0x00FFFFFF));
128 }
129 return Bitmap.createBitmap(argb, bm.getWidth(), bm.getHeight(),
130 Config.ARGB_8888);
131 }
132
133 /**
134 *
135 * @param bm
136 * @note if bitmap is smaller than screen, you can scale it fill the screen.
137 * @return
138 */
139 private Bitmap scaleBitmapFillScreen(Bitmap bm) {
140 return Bitmap.createScaledBitmap(bm, SCREEN_W, SCREEN_H, true);
141 }
142
143
144 private void setBackGround() {
145 setBackgroundResource(R.drawable.background);
146 }
147
148 /**
149 *
150 * @param bm
151 * @note set cover bitmap , which overlay on background.
152 */
153 private void setCoverBitmap(Bitmap bm) {
154 // setting paint
155 mPaint = new Paint();
156 mPaint.setAlpha(0);
157 mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
158 mPaint.setAntiAlias(true);
159
160 mPaint.setDither(true);
161 mPaint.setStyle(Paint.Style.STROKE);
162 mPaint.setStrokeJoin(Paint.Join.ROUND);
163 mPaint.setStrokeCap(Paint.Cap.ROUND);
164 mPaint.setStrokeWidth(20);
165
166 //set path
167 mPath = new Path();;
168
169 // converting bitmap into mutable bitmap
170 mBitmap = Bitmap.createBitmap(SCREEN_W, SCREEN_H, Config.ARGB_8888);
171 mCanvas = new Canvas();
172 mCanvas.setBitmap(mBitmap);
173 // drawXY will result on that Bitmap
174 // be sure parameter is bm, not mBitmap
175 mCanvas.drawBitmap(bm, 0, 0, null);
176 }
177
178
179
180 @Override
181 protected void onDraw(Canvas canvas) {
182 canvas.drawBitmap(mBitmap, 0, 0, null);
183 mCanvas.drawPath(mPath, mPaint);
184 super.onDraw(canvas);
185 }
186
187 private void touch_start(float x, float y) {
188 mPath.reset();
189 mPath.moveTo(x, y);
190 mX = x;
191 mY = y;
192 }
193 private void touch_move(float x, float y) {
194 float dx = Math.abs(x - mX);
195 float dy = Math.abs(y - mY);
196 if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
197 mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
198 mX = x;
199 mY = y;
200 }
201 }
202 private void touch_up() {
203 mPath.lineTo(mX, mY);
204 // commit the path to our offscreen
205 mCanvas.drawPath(mPath, mPaint);
206 // kill this so we don't double draw
207 mPath.reset();
208 }
209
210 @Override
211 public boolean onTouchEvent(MotionEvent event) {
212 float x = event.getX();
213 float y = event.getY();
214
215 switch (event.getAction()) {
216 case MotionEvent.ACTION_DOWN:
217 touch_start(x, y);
218 invalidate();
219 break;
220 case MotionEvent.ACTION_MOVE:
221 touch_move(x, y);
222 invalidate();
223 break;
224 case MotionEvent.ACTION_UP:
225 touch_up();
226 invalidate();
227 break;
228 }
229 return true;
230 }
231 }
232 }
2.利用canvas的drawCircle做擦除效果
效果如下:
实现代码:
233 package aliusa.cn;
234
235 import android.app.Activity;
236 import android.content.Context;
237 import android.graphics.Bitmap;
238 import android.graphics.BitmapFactory;
239 import android.graphics.Canvas;
240 import android.graphics.Paint;
241 import android.graphics.PorterDuff;
242 import android.graphics.PorterDuffXfermode;
243 import android.graphics.Bitmap.Config;
244 import android.os.Bundle;
245 import android.util.DisplayMetrics;
246 import android.view.MotionEvent;
247 import android.view.View;
248
249 public class Eraser_Use_drawCircle extends Activity {
250
251 private int SCREEN_W;
252
253 private int SCREEN_H;
254
255 @Override
256 protected void onCreate(Bundle savedInstanceState) {
257 super.onCreate(savedInstanceState);
258 setContentView(new MyView(this));
259
260 }
261
262 class MyView extends View {
263 private Bitmap mBitmap;
264 private Canvas mCanvas;
265 private Paint mPaint;
266 int x = 0;
267
268 int y = 0;
269
270 int r = 0;
271
272 public MyView(Context context) {
273 super(context);
274 setFocusable(true);
275 setScreenWH();
276 setBackGround();
277
278 // 1.if cover is a image,you can open MENU_ITEM_COMMENT bellow
279 Bitmap bm = createBitmapFromSRC();
280 // if you want to set cover image's alpha,you can open MENU_ITEM_COMMENT bellow
281 bm = setBitmapAlpha(bm, 100);
282 // if you want to scale cover image,you can open MENU_ITEM_COMMENT bellow
283 bm = scaleBitmapFillScreen(bm);
284
285 // 2.if cover is color
286 //Bitmap bm = createBitmapFromARGB(0x8800ff00, SCREEN_W, SCREEN_H);
287 setCoverBitmap(bm);
288
289 }
290
291 private void setScreenWH() {
292 // get screen info
293 DisplayMetrics dm = new DisplayMetrics();
294 dm = this.getResources().getDisplayMetrics();
295 // get screen width
296 int screenWidth = dm.widthPixels;
297 // get screen height
298 int screenHeight = dm.heightPixels;
299
300 SCREEN_W = screenWidth;
301 SCREEN_H = screenHeight;
302 }
303
304 private Bitmap createBitmapFromSRC() {
305 return BitmapFactory.decodeResource(getResources(),
306 R.drawable.cover);
307 }
308
309 /**
310 *
311 * @param colorARGB should like 0x8800ff00
312 * @param width
313 * @param height
314 * @return
315 */
316 private Bitmap createBitmapFromARGB(int colorARGB, int width, int height) {
317 int[] argb = new int[width * height];
318
319 for (int i = 0; i < argb.length; i++) {
320
321 argb[i] = colorARGB;
322
323 }
324 return Bitmap.createBitmap(argb, width, height, Config.ARGB_8888);
325 }
326
327 /**
328 *
329 * @param bm
330 * @param alpha ,and alpha should be like ox00000000-oxff000000
331 * @note set bitmap's alpha
332 * @return
333 */
334 /* private Bitmap setBitmapAlpha(Bitmap bm, int alpha) {
335 int[] argb = new int[bm.getWidth() * bm.getHeight()];
336 bm.getPixels(argb, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm
337 .getHeight());
338
339
340 for (int i = 0; i < argb.length; i++) {
341
342 argb[i] = ((alpha) | (argb[i] & 0x00FFFFFF));
343 }
344 return Bitmap.createBitmap(argb, bm.getWidth(), bm.getHeight(),
345 Config.ARGB_8888);
346 }*/
347
348 /**
349 *
350 * @param bm
351 * @param alpha ,alpha should be between 0 and 255
352 * @note set bitmap's alpha
353 * @return
354 */
355 private Bitmap setBitmapAlpha(Bitmap bm, int alpha) {
356 int[] argb = new int[bm.getWidth() * bm.getHeight()];
357 bm.getPixels(argb, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm
358 .getHeight());
359
360 for (int i = 0; i < argb.length; i++) {
361
362 argb[i] = ((alpha << 24) | (argb[i] & 0x00FFFFFF));
363 }
364 return Bitmap.createBitmap(argb, bm.getWidth(), bm.getHeight(),
365 Config.ARGB_8888);
366 }
367
368 /**
369 *
370 * @param bm
371 * @note if bitmap is smaller than screen, you can scale it fill the screen.
372 * @return
373 */
374 private Bitmap scaleBitmapFillScreen(Bitmap bm) {
375 return Bitmap.createScaledBitmap(bm, SCREEN_W, SCREEN_H, true);
376 }
377
378
379 private void setBackGround() {
380 setBackgroundResource(R.drawable.background);
381 }
382
383 /**
384 *
385 * @param bm
386 * @note set cover bitmap , which overlay on background.
387 */
388 private void setCoverBitmap(Bitmap bm) {
389 // setting paint
390 mPaint = new Paint();
391 mPaint.setAlpha(0);
392 mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
393 mPaint.setAntiAlias(true);
394
395 // converting bitmap into mutable bitmap
396 mBitmap = Bitmap.createBitmap(SCREEN_W, SCREEN_H, Config.ARGB_8888);
397 mCanvas = new Canvas();
398 mCanvas.setBitmap(mBitmap);
399 // drawXY will result on that Bitmap
400 // be sure parameter is bm, not mBitmap
401 mCanvas.drawBitmap(bm, 0, 0, null);
402 }
403
404
405
406 @Override
407 protected void onDraw(Canvas canvas) {
408 // draw a circle that is erasing bitmap
409 mCanvas.drawCircle(x, y, r, mPaint);
410 canvas.drawBitmap(mBitmap, 0, 0, null);
411 super.onDraw(canvas);
412 }
413
414 @Override
415 public boolean onTouchEvent(MotionEvent event) {
416 // set parameter to draw circle on touch event
417 x = (int) event.getX();
418 y = (int) event.getY();
419 r = 20;
420 // Atlast invalidate canvas
421 invalidate();
422 return true;
423 }
424 }