今天介绍一下在Android当中怎么扭曲图像,在Android系统中的Canvas提供了一个drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts, int vertOffset, int[] colors, int colorOffset, Paint paint)方法可以扭曲图像,该方法可以对bitmap进行扭曲。参数说明:
bitmap:指定需要扭曲的源位图;
meshWidth:该参数控制在横向上把该源位图划分成多少格;
meshHeight:该参数控制在纵向上把该源位图划分成多少格;
verts:该参数是一个长度为(meshWidth+1)*(meshHeight+1)*2的数组,它记录了扭曲后的位图各“顶点”位置。虽然它是个数组,实际上它记录的数据是形如(x0,y0)、(x1,y1)、(x2,y2)....(Nx,Ny)格式的数据,这些数组元素控制对bitmap位图的扭曲效果;
vertOffset:控制verts数组中从第几个数组元素开始才对bitmap进行扭曲。
下面就直接上一个实例:
1 public class WarpTest extends Activity 2 { 3 private Bitmap bitmap; 4 @Override 5 public void onCreate(Bundle savedInstanceState) 6 { 7 super.onCreate(savedInstanceState); 8 setContentView(new MyView(this , R.drawable.jinta)); 9 } 10 private class MyView extends View 11 { 12 //定义两个常量,这两个常量指定该图片横向、纵向上都被划分为20格。 13 private final int WIDTH = 20; 14 private final int HEIGHT = 20; 15 //记录该图片上包含441个顶点 16 private final int COUNT = (WIDTH + 1) * (HEIGHT + 1); 17 //定义一个数组,保存Bitmap上的21 * 21个点的座标 18 private final float[] verts = new float[COUNT * 2]; 19 //定义一个数组,记录Bitmap上的21 * 21个点经过扭曲后的座标 20 //对图片进行扭曲的关键就是修改该数组里元素的值。 21 private final float[] orig = new float[COUNT * 2]; 22 public MyView(Context context , int drawableId) 23 { 24 super(context); 25 setFocusable(true); 26 //根据指定资源加载图片 27 bitmap = BitmapFactory.decodeResource(getResources(), 28 drawableId); 29 //获取图片宽度、高度 30 float bitmapWidth = bitmap.getWidth(); 31 float bitmapHeight = bitmap.getHeight(); 32 int index = 0; 33 for (int y = 0; y <= HEIGHT; y++) 34 { 35 float fy = bitmapHeight * y / HEIGHT; 36 for (int x = 0; x <= WIDTH; x++) 37 { 38 float fx = bitmapWidth * x / WIDTH; 39 /* 40 * 初始化orig、verts数组。 41 * 初始化后,orig、verts两个数组均匀地保存了21 * 21个点的x,y座标 42 */ 43 orig[index * 2 + 0] = verts[index * 2 + 0] = fx; 44 orig[index * 2 + 1] = verts[index * 2 + 1] = fy; 45 index += 1; 46 } 47 } 48 //设置背景色 49 setBackgroundColor(Color.WHITE); 50 } 51 52 @Override 53 protected void onDraw(Canvas canvas) 54 { 55 /* 对bitmap按verts数组进行扭曲 56 * 从第一个点(由第5个参数0控制)开始扭曲 57 */ 58 canvas.drawBitmapMesh(bitmap, WIDTH, HEIGHT, verts 59 , 0, null, 0, null); 60 } 61 //工具方法,用于根据触摸事件的位置计算verts数组里各元素的值 62 private void warp(float cx, float cy) 63 { 64 for (int i = 0; i < COUNT * 2; i += 2) 65 { 66 float dx = cx - orig[i + 0]; 67 float dy = cy - orig[i + 1]; 68 float dd = dx * dx + dy * dy; 69 //计算每个座标点与当前点(cx、cy)之间的距离 70 float d = (float)Math.sqrt(dd); 71 //计算扭曲度,距离当前点(cx、cy)越远,扭曲度越小 72 float pull = 80000 / ((float) (dd * d)); 73 //对verts数组(保存bitmap上21 * 21个点经过扭曲后的座标)重新赋值 74 if (pull >= 1) 75 { 76 verts[i + 0] = cx; 77 verts[i + 1] = cy; 78 } 79 else 80 { 81 //控制各顶点向触摸事件发生点偏移 82 verts[i + 0] = orig[i + 0] + dx * pull; 83 verts[i + 1] = orig[i + 1] + dy * pull; 84 } 85 } 86 //通知View组件重绘 87 invalidate(); 88 } 89 @Override 90 public boolean onTouchEvent(MotionEvent event) 91 { 92 //调用warp方法根据触摸屏事件的座标点来扭曲verts数组 93 warp(event.getX(), event.getY()); 94 return true; 95 } 96 } 97 }