Android学习之图像的处理

来源:互联网 发布:购物分享php系统 编辑:程序博客网 时间:2024/05/29 08:46

Android系统提供了Matrix对象控制图形进行平移、旋转、缩放、倾斜等操作,对View组件也可以进行平移、旋转、缩放等。

import android.content.Context;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Matrix;import android.graphics.drawable.BitmapDrawable;import android.util.AttributeSet;import android.view.KeyEvent;import android.view.View; public class MyView extends View{// 初始的图片资源private Bitmap bitmap;// Matrix 实例private Matrix matrix = new Matrix();// 设置倾斜度private float sx = 0.0f;// 位图宽和高private int width, height;// 缩放比例private float scale = 1.0f;// 判断缩放还是旋转private boolean isScale = false;public MyView(Context context , AttributeSet set){super(context , set);// 获得位图bitmap = ((BitmapDrawable) context.getResources().getDrawable(R.drawable.a)).getBitmap();// 获得位图宽width = bitmap.getWidth();// 获得位图高height = bitmap.getHeight();// 使当前视图获得焦点this.setFocusable(true);}protected void onDraw(Canvas canvas){super.onDraw(canvas);// 重置Matrixmatrix.reset();if (!isScale){// 旋转Matrixmatrix.setSkew(sx, 0);}else{// 缩放Matrixmatrix.setScale(scale, scale);}// 根据原始位图和Matrix创建新图片Bitmap bitmap2 = Bitmap.createBitmap(bitmap, 0, 0, width, height,matrix, true);// 绘制新位图canvas.drawBitmap(bitmap2, matrix, null);}public boolean onKeyDown(int keyCode, KeyEvent event){switch(keyCode){// 按键A向左倾斜case KeyEvent.KEYCODE_A:isScale = false;sx += 0.1;postInvalidate();break;// 按键D向右倾斜case KeyEvent.KEYCODE_D:isScale = false;sx -= 0.1;postInvalidate();break;// 按键W放大case KeyEvent.KEYCODE_W:isScale = true;if (scale < 2.0)scale += 0.1;postInvalidate();break;// 按键S缩小case KeyEvent.KEYCODE_S:isScale = true;if (scale > 0.5)scale -= 0.1;postInvalidate();break;}return super.onKeyDown(keyCode, event);}}


Canvas提供了一个drawBitmapMesh方法对Bitmap对象进行扭曲,其效果相当于PS里的滤镜,可以做出水波荡漾、红旗飘飘等扭曲效果。

drawBitmapMesh(Bitmap bitmap, int meshWidth,int meshHeight,float[] verts,int vertOffset,int[] colors,int colorOffset,Paint paint)

其中bitmap为需要扭曲的图源,meshWidth和meshHeight分别是横向和纵向上把bitmap分成多少格,

verts是一个长度为(meshWidth+1)*(meshHeight+1)

vertOffset控制verts数组从第几个数组元素开始才对bitmap进行扭曲

import android.app.Activity;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.os.Bundle;import android.view.MotionEvent;import android.view.View;public class WarpTest extends Activity{private Bitmap bitmap;public void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(new MyView(this, R.drawable.jinta));}private class MyView extends View{// 定义两个常量,这两个常量指定该图片横向、纵向上都被划分为20格。private final int WIDTH = 20;private final int HEIGHT = 20;// 记录该图片上包含441个顶点private final int COUNT = (WIDTH + 1) * (HEIGHT + 1);// 定义一个数组,保存Bitmap上的21 * 21个点的座标private final float[] verts = new float[COUNT * 2];// 定义一个数组,记录Bitmap上的21 * 21个点经过扭曲后的座标// 对图片进行扭曲的关键就是修改该数组里元素的值。private final float[] orig = new float[COUNT * 2];public MyView(Context context, int drawableId){super(context);setFocusable(true);// 根据指定资源加载图片bitmap = BitmapFactory.decodeResource(getResources(), drawableId);// 获取图片宽度、高度float bitmapWidth = bitmap.getWidth();float bitmapHeight = bitmap.getHeight();int index = 0;for (int y = 0; y <= HEIGHT; y++){float fy = bitmapHeight * y / HEIGHT;for (int x = 0; x <= WIDTH; x++){float fx = bitmapWidth * x / WIDTH;// 初始化orig、verts数组。 初始化后,orig、verts// 两个数组均匀地保存了21 * 21个点的x,y座标orig[index * 2 + 0] = verts[index * 2 + 0] = fx;orig[index * 2 + 1] = verts[index * 2 + 1] = fy;index += 1;}}// 设置背景色setBackgroundColor(Color.WHITE);}protected void onDraw(Canvas canvas){//对bitmap按verts数组进行扭曲//从第一个点(由第5个参数0控制)开始扭曲canvas.drawBitmapMesh(bitmap, WIDTH, HEIGHT, verts, 0, null, 0,null);}// 工具方法,用于根据触摸事件的位置计算verts数组里各元素的值private void warp(float cx, float cy){for (int i = 0; i < COUNT * 2; i += 2){float dx = cx - orig[i + 0];float dy = cy - orig[i + 1];float dd = dx * dx + dy * dy;// 计算每个座标点与当前点(cx、cy)之间的距离float d = (float) Math.sqrt(dd);// 计算扭曲度,距离当前点(cx、cy)越远,扭曲度越小float pull = 80000 / ((float) (dd * d));// 对verts数组(保存bitmap上21 * 21个点经过扭曲后的座标)重新赋值if (pull >= 1){verts[i + 0] = cx;verts[i + 1] = cy;}else{// 控制各顶点向触摸事件发生点偏移verts[i + 0] = orig[i + 0] + dx * pull;verts[i + 1] = orig[i + 1] + dy * pull;}}// 通知View组件重绘invalidate();}public boolean onTouchEvent(MotionEvent event){// 调用warp方法根据触摸屏事件的座标点来扭曲verts数组warp(event.getX(), event.getY());return true;}}}


使用Shader填充图形

Shader本身是一个抽象类,它提供了如下实现类

BitmapShader  使用位图平铺的渲染效果

LinearGradient 使用线性渐变来填充图形

RadialGradient 使用圆形渐变来填充图形

WseepGradient 使用角度渐变来填充图形

ComposeShader 使用组合渲染效果来填充图形




import android.app.Activity;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.BitmapShader;import android.graphics.Color;import android.graphics.ComposeShader;import android.graphics.LinearGradient;import android.graphics.PorterDuff;import android.graphics.RadialGradient;import android.graphics.Shader;import android.graphics.SweepGradient;import android.graphics.Shader.TileMode;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;public class ShaderTest extends Activityimplements OnClickListener{// 声明位图渲染对象private Shader[] shaders = new Shader[5];// 声明颜色数组private int[] colors;MyView myView;// 自定义视图类public void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);myView = (MyView)findViewById(R.id.my_view);// 获得Bitmap实例Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.water);// 设置渐变的颜色组,也就是按红、绿、蓝的方式渐变colors = new int[] { Color.RED, Color.GREEN, Color.BLUE };// 实例化BitmapShader,x坐标方向重复图形,y坐标方向镜像图形shaders[0] = new BitmapShader(bm, TileMode.REPEAT,TileMode.MIRROR);// 实例化LinearGradientshaders[1] = new LinearGradient(0, 0, 100, 100, colors, null, TileMode.REPEAT);// 实例化RadialGradientshaders[2] = new RadialGradient(100, 100, 80, colors, null,TileMode.REPEAT);// 实例化SweepGradientshaders[3] = new SweepGradient(160, 160, colors, null);// 实例化ComposeShadershaders[4] = new ComposeShader(shaders[1], shaders[2],PorterDuff.Mode.DARKEN);Button bn1 = (Button)findViewById(R.id.bn1);Button bn2 = (Button)findViewById(R.id.bn2);Button bn3 = (Button)findViewById(R.id.bn3);Button bn4 = (Button)findViewById(R.id.bn4);Button bn5 = (Button)findViewById(R.id.bn5);bn1.setOnClickListener(this);bn2.setOnClickListener(this);bn3.setOnClickListener(this);bn4.setOnClickListener(this);bn5.setOnClickListener(this);}public void onClick(View source){switch(source.getId()){case R.id.bn1:myView.paint.setShader(shaders[0]);break;case R.id.bn2:myView.paint.setShader(shaders[1]);break;case R.id.bn3:myView.paint.setShader(shaders[2]);break;case R.id.bn4:myView.paint.setShader(shaders[3]);break;case R.id.bn5:myView.paint.setShader(shaders[4]);break;}// 重绘界面myView.invalidate();}}


0 0