Android的图形与图像处理之一 使用简单图片&绘图

来源:互联网 发布:网络拒绝接入怎么解决 编辑:程序博客网 时间:2024/05/17 22:33
R.drawable.file_name是一个int常量,若想获取实际的Drawable对象,可调用Resource的getDrawable(int id)获取


Bitmap与BitmapFactory
BitmapDrawable里封装的图片就是一个Bitmap对象,封装方法如下:
BitmapDrawable drawable = new BitmapDrawable(bitmap);
如果要获取BitmapDrawable所包装的Bitmap对象,则可调用BitmapDrawable的getBitmap()方法,示例如下:
Bitmap bitmap = drawable.getBitmap();
Bitmap还提供了一些静态方法来创建新的Bitmap对象,如下:
createBitmap(Bitmap source, int x, int y, int width, int height)
从源位图source的指定坐标开始,从中挖取width*height的一块来创建新Bitmap
createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter)
对源位图进行缩放,缩放成(dstWidth*dstHeight)的新位图
createBitmap(int width, int height, Bitmap.Config config)
创建一个宽width、高height的新位图
createBitmap(Bitmap source, int x, int y, int width, int height, Matrix m, boolean filter)
从源位图挖取一块指定宽高创建Bitmap对象,并按Matrix指定的规则变换
BitmapFactory包含大量方法
decodeByteArray(byte[] data, int offset, int length)
从指定字节数组的offset开始,将长度为length的字节数据解析成Bitmap对象
decodeFile(String pathName)
从pathName指定的文件中解析创建Bitmap对象
decodeFileDescriptor(FileDescriptor fd)
用于从FileDescriptor对应的文件
decodeResource(Resources res, int id)
根据给定资源ID从指定资源解析、创建
decodeStream(InputStream is)
从指定流中解析、创建
通常做法是把图片放在/res/drawabe-hdpi目录下,程序通过ID来获取对象。如果系统不停的去解析、创建Bitmap对象,可能由于前面创建Bitmap所占内存还没有回收,而导致程序发生OutOfMemory错误,为此设计了如下方法:
boolean isRecycled():返回是否已被回收
void recycle():强制一个Bitmap对象以及回收自己


绘图
Canvas、Paint
Android的绘图继承View组件,并重写它的onDraw(Canvas canvas)方法
API Canvas代表依附于指定View画布,它有如下方法:
除了上述方法外,Canvas还提供如下方法进行坐标变换:
rotate(float degrees,float px, float py)
对Canvas执行旋转变换
scale(float sx, float sy, float sy,float px, float py)
对Canvas执行缩放变换
skew(float sx, float sy)
对Canvas执行倾斜变换
translate(float dx, float dy)
移动Canvas。向右移动dx距离(dx为负则向左),向下移动dy距离(dy为负则向上)
Canvas提供上面的方法还涉及一个API:Paint,Paint代表了Canvas上的画笔,用于设置绘制风格
Paint常用方法:
setARGB(int a, int r, int g, int b)setColor(int color)
设置颜色
setAlpha(int a)
设置透明度
setAntiAlias(boolean aa)
设置是否抗锯齿
setColor(int color)

setPathEffect(PathEffect effect)
设置绘制路径时的路径效果
setShader(Shader shader)
设置画笔的填充效果
setShadowLayer(float radius, float dx, float dy, int color)
设置阴影
setStrokeWidth(float width)
设置画笔的笔触宽度
setStrikeJoin(Paint.Join join)
设置画笔转弯处的连接风格
setStyle(Paint.Style style)
设置Paint的填充风格
setTextAlign(Paint.Align align)
设置绘制文本时文字的对齐方式
setTextSize(float textSize)
大小
Canvas提供的绘制方法中还有一个API:Path,Path代表任意多条直线连接而成的任意图形,当Canvas根据Path绘制图形,它可以绘制出任意形状。还可以自定义一个View组件,重写它的onDraw(Canvas)方法。
Canvas不仅可以绘制简单图形,还可以直接将一个Bitmap绘制到画布上,这是极大的分工方便
下面详解Path类
Android还为路径绘制提供了PathEffect来定义绘制效果,PathEffect包含如下子类:
  • ComposePathEffect
  • CornerPathEffect
  • DashPathEffect
  • DiscretePathEffect
  • PathDashPathEffect
  • SumPathEffect
示例代码:
main.xml
publicclassPathTest extends ActionBarActivity {

   
@Override
   
protected void onCreate(Bundle savedInstanceState) {
       
super.onCreate(savedInstanceState);
        setContentView(
newMyView(this));
    }
   
class MyView extends View
    {
   
floatphase;
    PathEffect[]
effects = new PathEffect[7];
   
int[]colors;
   
privatePaint paint;
    Path
path;
   
publicMyView(Context context)
    {
   
super(context);
   
paint= new Paint();
   
paint.setStyle(Paint.Style.STROKE);
   
paint.setStrokeWidth(4);
   
path= new Path();
   
path.moveTo(0,0);
   
for(inti =1; i<= 15; i++)
    {
   
path.lineTo(i*20, (float)Math.random()*60);
    }
   
colors= new int[]{Color.BLACK,Color.BLUE, Color.CYAN
    , Color.
GREEN, Color.MAGENTA, Color.RED, Color.YELLOW};
    }
   
@Override
   
protectedvoidonDraw(Canvas canvas)
    {
    canvas.drawColor(Color.
WHITE);
   
effects[0]=null;
   
effects[1] =newCornerPathEffect(10);
   
effects[2] =newDiscretePathEffect(3.0f, 5.0f);
   
effects[3] =newDashPathEffect(newfloat[]{20,10,5,10},phase);
    Path p =
new Path();
    p.addRect(0,0,8,8,Path.Direction.
CCW);
   
effects[4] =newPathDashPathEffect(p,12,phase,
    PathDashPathEffect.Style.
ROTATE);
   
effects[5] =newComposePathEffect(effects[2],effects[4]);
   
effects[6] =newSumPathEffect(effects[4],effects[3]);
    canvas.translate(8, 8);
   
for(inti = 0; i<effects.length; i++)
    {
   
paint.setPathEffect(effects[i]);
   
paint.setColor(colors[i]);
    canvas.drawPath(
path,paint);
    canvas.translate(0, 60);
    }
   
phase+= 1;
    invalidate();
    }
    }
}
此外,Android的Canvas还提供了一个drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint)方法,该方法可以沿着Path绘制文本。
示例代码如下:
main.xml
publicclassPathTest extends ActionBarActivity {

   
@Override
   
protected void onCreate(Bundle savedInstanceState) {
       
super.onCreate(savedInstanceState);
        setContentView(
newTextView(this));
//        setContentView(new MyView(this));
    }
   
class TextView extends View
    {
   
finalString DRAW_STR = "android java";
    Path[]
paths = new Path[3];
    Paint
paint;
   
publicTextView(Context context)
    {
   
super(context);
   
paths[0] =newPath();
   
paths[0].moveTo(0, 0);
   
for(inti = 1; i<= 7;i++)
    {
   
paths[0].lineTo(i * 30, (float) Math.random() * 30);
    }
   
paths[1] =newPath();
    RectF rectF =
new RectF(0,0,200,120);
   
paths[1].addOval(rectF,Path.Direction.CCW);
   
paths[2] =newPath();
   
paths[2].addArc(rectF, 60, 180);
   
paint= new Paint();
   
paint.setAntiAlias(true);
   
paint.setColor(Color.CYAN);
   
paint.setStrokeWidth(1);
    }
   
@Override
   
protectedvoidonDraw(Canvas canvas)
    {
    canvas.drawColor(Color.
WHITE);
    canvas.translate(40, 40);
   
paint.setTextAlign(Paint.Align.RIGHT);
   
paint.setTextSize(20);
   
paint.setStyle(Paint.Style.STROKE);
    canvas.drawPath(
paths[0],paint);
   
paint.setStyle(Paint.Style.FILL);
    canvas.drawTextOnPath(
DRAW_STR,paths[0],-8,20,paint);
    canvas.translate(0, 60);
   
paint.setStyle(Paint.Style.STROKE);
    canvas.drawPath(
paths[1],paint);
   
paint.setStyle(Paint.Style.FILL);
    canvas.drawTextOnPath(
DRAW_STR,paths[1], -20, 20,paint);
    canvas.translate(0, 120);
   
paint.setStyle(Paint.Style.STROKE);
    canvas.drawPath(
paths[2],paint);
   
paint.setStyle(Paint.Style.FILL);
    canvas.drawTextOnPath(
DRAW_STR,paths[2], -10, 20,paint);
    }
    }
}


绘制游戏动画
动画其实就是不断地重复调用View组件的onDraw(Canvas canvas)方法
如果要View上绘制的图形发生部分改变,就需要程序采用变量来“记住”这些状态数据;
如果需要游戏动画随着用户操作而改变,就需要为用户动作编写事件监听器;
如果需要游戏动画自动改变,就需要使用Timer控制状态数据修改;

绘图中,为了保留用户之间绘制的内容,程序需要借助“双缓冲”技术。
(双缓冲:当程序需要在指定View上进行绘制时,程序并不直接绘制到该View组件上,而是先绘制到一个内存中的Bitmap上,等到内存中的Bitmap绘制好之后,再一次性将Bitmap绘制到View组件上)
0 0
原创粉丝点击