图形与图像的处理

图形与图像的处理

一、使用简单的图片

   在之前的在android应用中已经大量使用图片,图片不仅可以使用imageview,imagebutton,来显示,也可以用作组件的背景,比如,button,window;从广义角度来看。android应用中的图片不仅包括*png,*jpg,*gif等各种格式的位图,也包括使用xml资源文件定义的各种Drawable对象;

1.使用drawable对象;

 在我们为android应用增加了Drawable资源之后,Android sdk 会为这份资源在R清单文件中创建一个索引项:
 在xml文件中:通过@drawable/file_name来访问该drawable对象
 在java代码中:R.drawable.file_name来访问该drawable对象;
 注意:
     这里的r.drawable.file_name是一个int类型的常量,如果在java程序中想要访问drawable对象,则可以调用Resources的getDrawable(int id)方法来获取。

2.Bitmap和BitmapFactory

 1)Bitmap类代表一张位图;BitmapDrawable里封装的图片就是一个Bitmap对象;

把一个Bitmap对象包装成BitmapDrawable对象
BitmapDrawable drawable=new BitmapDrawable(bitmap);
从BitmapDrawable内拿到Bitmap对象
Bitmap bitmap=drawable.getBitmap();

bitmap 还提供了许多静态方法来创建新的的Bitmap对象,例如
createBitmap(Bitmap source,int x,int y,int width,int height)从源位图source 的指定坐标点(x,y)开始,从中挖去宽width,高height的一块出来,创建新的Bitmap对象。
createBitmap(Bitmap source, int x, int y, int width, int height, Matrix m, boolean filter)
从源位图source的指定坐标点(x,y)开始,从中挖去宽width,高height的一块出来,创建新的Bitmap对象。并且按照Matrix指定的规则进行变换;
createBitmap(int width,int height,Bitmap.Config config)创建一个宽width高height的新位图;
createScaledBitmap(Bitmap src,int dstwidth,int dstheight,boolean filter)对源位图进行缩放,缩放成宽dstwidth,高dstheight的新位图;
2). BitmapFactory是一个工具类,它用于提供大量的方法,这些方法可以用于从不同的数据源来解析、创建位图对象。
bitmap包含了如下方法:
decodeByteArray(byte[]data,int offset,int length):从指定字节数组offset位置开始,将长度为length的字节数据解析成Bitmap对象;
decodeFile(String pathName)从pathName指定的文件中解析、创建Bitmap对象;
decodeFileDescriptor(FileDescriptor fd):用于从FileDescriptor对应的文件中解析创建位图对象;
decodeResource(Resource res,int id);用于根据指定资源id从指定资源中解析创建Bitmap对象;
decodeStream(InputStream is):用于从指定的输入流中解析、创建Bitmap对象;
大部分时候,我们只要把图片存在/res/drawable-mdpi目录中,就可以在程序中通过该图片对应的资源id来获取封装该图片的Drawable对象。但由于手机系统内存比较小,系统不停地去解析、创建Bitmap对象,可能由于前面创建的Bitmap所占用的内从还没有回收,可能导致程序运行行引发OutOfMemory错误;
Android为Bitmap提供两个方法来判断它是否回收,以及强制Bitmap回收自己。
boolean isRecycled():返回该Bitmap对象是否已被回收;
void recycle():强制一个bitmap对象立即回收自己;
除此之外,如果android应用需要访问其他存储路径(比如sd卡)里的图片,这时候都需要借助BitmapFactory对象来解析、创建Bitmp对象;

二、绘图

除了使用已有的图片外,Android应用常常需要在运行时动态的显示图片,比如手机游戏,不仅看上去界面丰富多彩,而且可以随着用户动作而动态的改变,这就需要借助于android的绘图支持了;

1.android的绘图基础Canvas、paint、path;

在android中,绘图继承View组件,并且重写ondraw(Canvas canvas)方法即可;
重写onDraw(Canvas canvas)方法时涉及到绘图api canvas,canvas代表了“依附”于指定View的画布;
1)Canvas的绘制方法:
void drawRect(RectF rect, Paint paint) //绘制区域,参数一为RectF一个区域
void drawPath(Path path, Paint paint) //绘制一个路径,参数一为Path路径对象
void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) //贴图,参数一就是我们常规的Bitmap对象,参数二是源区域(这里是bitmap),参数三是目标区域(应该在 canvas的位置和大小),参数四是Paint画刷对象,因为用到了缩放和拉伸的可能,当原始Rect不等于目标Rect时性能将会有大幅损失。
void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) //画线,参数一起始点的x轴位置,参数二起始点的y轴位置,参数三终点的x轴水平位置,参数四y轴垂直位置,最后一个参数为Paint画刷对象。
void drawPoint(float x, float y, Paint paint) //画点,参数一水平x轴,参数二垂直y轴,第三个参数为Paint对象。
void drawText(String text, float x, float y, Paint paint) //渲染文本,Canvas类除了上面的还可以描绘文字,参数一是String类型的文本,参数二x轴,参数三y轴,参数四是Paint对象。
void drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint) //可以沿着路径绘制文本,相对于上面第二个参数是Path路径对象,hoffset参数指定的是水平偏移,voffset参数指定的时垂直偏移;
void drawBitmapMesh()

2)paint:代表了Canvas上的画笔,因此paint类主要用于设置绘制风格,包括画笔颜色、画笔笔触粗细、填充风格。。
例如:void setARGB(int a, int r, int g, int b) 设置颜色
void setAlpha(int a);设置透明值
void setAntiAlias(boolean aa) ;设置是否抗锯齿;
void setColor(int color) Set the paint’s color.
PathEffect setPathEffect(PathEffect effect) 设置绘制路径时的路径效果;
void setStrokeJoin(Paint.Join join);设置画笔转弯处的连接风格
void setStrokeWidth(float width) ;设置画笔的笔触宽度;
void setStyle(Paint.Style style) ;设置paint的填充风格
void setTextAlign(Paint.Align align) ;设置绘制文本时的文字对齐方式;
void setTextSize(float textSize) ;设置绘制文本时的文字大小
3 )path:
path可以预先在View上将N个点连成一条“路径”,然后调用Canvas的Drawpath(path,paint)即可沿着路径绘制图形;
android 还为路径绘制提供了PathEffect来定义绘制效果,pathEffect包含如下子类;
ComposePathEffect;
CornerPathEffect:
DashPathEffect:
DiscreatePathEffect:
PathDashPathEffect:
SumPathEffect:

4)绘制游戏动画
在掌握了canvas绘图之后,如果需要实现游戏动画也是相当容易的;动画其实就是不断地重复调用View组件的ondraw(Canvas canvas)方法,如果每次在view组件上绘制的图形并不相同,就成了所谓的动画;
而让view组件上绘制的图形发生改变(也就是位置、大小、角度、颜色。。。发生变化),这时候就需要程序采用变量来“记住”这些状态数据;
1.如果是需要游戏动画随着用户的操作而改变,就为用户动作编写事件监听器,在监听器中修改这些数据;
2.如果是需要游戏动画“自动”的改变,那就是随着时间流失而改变,就需要使用定时器(Timer),让Timer控制这些数据的改变;
不管使用哪种方式,每次view组件上的图形状态发生改变之后了,都应该通知View组件重写调用ondraw(Canvas canvas)方法重绘组件。通知View重绘可调用invalidate();(在ui线程中)
在非ui线程中,用postInvalidate();

实例:
1)采用双缓冲实现画图板;
当用户在触摸屏上移动时,即可在屏幕上绘制任意的图形;实现手绘功能其实是一种假象,实际上它采用的还是Canvas的drawline方法画直线,每条直线都是从上一次拖动事件的发生点到本次事件的发生点。当用户在触摸屏上移动时,两次拖动的距离很小,多条极短的直线连在一起,看起来就是一条直线了。借助于android的path类,很容易实现这个效果;
注意:
如果程序每次都是从上一次的拖动事件的发生点绘制一条直线到本次拖动事件发生点,那么用户前面的数据就会丢失,为了保留用户之前绘制的内容,程序需要借助“双缓冲”技术;
双缓冲技术:当程序需要在指定的view上进行绘制时,程序并不直接绘制到view组件上,而是先绘制到内从中的bitmap(这就是双缓冲)上,等绘制好后,在将bitmap绘制到view上;

三、图形特效处理

android除了前面介绍的这些图像支持外,还提供了一些额外的更高级的图形特效支持,这些支持可以让开发者开出更绚丽的“ui”界面;
使用matrix控制变化;
matrix是android提供的一个矩阵类,它本身不能对图像或组件进行变换,但它可与其他的api结合来控制图形、组件的变换;
使用matrix控制图像或组件的步骤如下
1,获取matrix对象,该对象可以新建,也可以从其他对象里获取(比如Transformation对象内部就封装了matrix对象)
2.调用martix对象的方法进行平移、旋转、缩放、倾斜。。。
3.将程序对martix对象所作的变化应用到指定的图像或组件;
martix提供了如下方法进行平移、旋转、缩放、倾斜。。。
setTranslate(float x,float y)控制martix进行平移;
setSkew(float kx,float ky,float px,float py)控制martix以px,py为轴心进行倾斜,kx,ky为x,y方向上倾斜的距离;
setSew(float kx,float ky) 控制martix进行倾斜;kx,ky为x,y方向上倾斜的距离;
SetRoate(float degrees)控制martix进行旋转,degrees控制旋转的角度
setRoate(float degrees,float px,float py)设置以px,py为轴心旋转,degrees控制旋转角度;
setScale(float sx,float sy)控制martix进行缩放,sx,sy为控制想,x,y方向上的缩放比例;
setScale(float sx,float sy,float px,float py)控制martix以px,py为轴心进行缩放,sx,sy为控制想,x,y方向上的缩放比例;

drawBitmap(Bitmap bitmap,Martix martix,Paint paint)

四、逐帧(Frame)动画

逐帧是最容易理解的动画,他要求开发者把动画过程的每张静态图片都收集起来,然后由android来控制依次显示这些静态图片,然后利用人眼“视觉暂留”的原理,给用户造成“动画”的错觉,逐帧动画的原理与放电影的原理一样;

摘自《疯狂android 讲义》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值