android学习日记09--BitMap操作
Bitmap
android里的图像处理重要的类,支持jpg、png、bmp等格式的图像,BitmapDrawable是封装Bitmap的一个对象,
Bitmap实现在android.graphics包中。但是Bitmap类的构造函数是私有的,外面并不能实例化,只能是通过JNI(Java Native Interface JAVA本地调用)实例化。这必然是 某个辅助类提供了创建Bitmap的接口,而这个类的实现通过JNI接口来实例化Bitmap的,这个类就是BitmapFactory。利用BitmapFactory可以从一个指定文件中,利用decodeFile()解出Bitmap;也可以定义的图片资源中,利用decodeResource()解出Bitmap
android支持一些方法对图像的平移、剪切、旋转、缩放等操作这样子可以用一张图片经过变化得到自己想要的,节省很多系统资源。
由于手机系统资源有限,没用的图像要及时回收,否则会产生OOM,isRecycled()判读该Bitmap是否可回收,recycle()强制Bitmap自我回收。
1、android 系统图像的简单变化例子:
1 // 获取图标图像的实例 2 Bitmap bitmap = BitmapFactory.decodeResource(this.getResources()
, R.drawable.ic_launcher); 3 // 绘制图像 4 canvas.drawBitmap(bitmap, 0, 0, paint); 5 // 保存当前状态 6 canvas.save(); 7 8 // 绕图像中点旋转90度 9 canvas.rotate(30, bitmap.getWidth()/2, bitmap.getHeight()/2); 10 // 为了不重叠,画在(50,0)这点,x,y轴相对旋转也发生变化 11 canvas.drawBitmap(bitmap, 50, 0, paint); 12 13 //恢复上次保存的状态与save()对应 14 canvas.restore(); 15 canvas.drawBitmap(bitmap, 100, 100, paint); 16 17 //平移 18 canvas.translate(0, 50); 19 canvas.drawBitmap(bitmap, 100, 100, paint); 20 21 // 缩放,参数分别表示:x轴缩放2倍,y轴缩放2倍,3,4参数表示缩放的起始点 22 canvas.scale(2, 2, 50+bitmap.getWidth()/2, 50+bitmap.getHeight()/2); 23 canvas.drawBitmap(bitmap, 100, 100, paint); 24 25 // 相对y轴镜像 26 canvas.scale(1, -1, 50+bitmap.getWidth()/2, 50+bitmap.getHeight()/2); 27 canvas.drawBitmap(bitmap, 100, 100, paint);
效果如下:
2、png格式和其他图像格式的区别是,png图像支持背景是透明的,
可以多个图像叠加在一起,而其他格式的图片就会被旁白覆盖
1 //绘制一张背景图片,充满整个屏幕 2 Bitmap bitmap1 = BitmapFactory.decodeResource(this.getResources()
, R.drawable.background); 3 canvas.drawBitmap(bitmap1, 0, 0, paint); 4 5 // png的图片,左边螃蟹边缘是透明的,因此不会有问题 6 Bitmap bitmap2 = BitmapFactory.decodeResource(this.getResources()
, R.drawable.crab); 7 canvas.drawBitmap(bitmap2, 20, 200, paint); 8 9 // jpg的图片,右边螃蟹边缘把背景遮挡了 10 Bitmap bitmap3 = BitmapFactory.decodeResource(this.getResources()
, R.drawable.carb2); 11 canvas.drawBitmap(bitmap3, 200, 230, paint);
效果图如下:
左边的螃蟹图片是png格式的,右边则是jpg格式的,明显右边螃蟹还留有矩形的空白。
3、Bitmap通过均匀改变draw的横纵坐标或者切换图片就会呈现动画的效果,
上图是一张波浪的图片
canvas.drawBitmap(bmp, x, y, new Paint());
新建个线程:x+=1,就可以看到海水在动。
上面则是9张卡通鱼的图片,分别命名fish0~fish9,通过来回不断切换图片,就会看到鱼儿在游动
运行效果(由于博主不会录制gif图片,囧!就截2张图,读者自己脑补吧):
SurfaceView主要代码:
1 public MySurfaceView(Context context) { 2 super(context); 3 // TODO Auto-generated constructor stub 4 sfh = this.getHolder(); 5 sfh.addCallback(this); 6 paint = new Paint(); 7 paint.setColor(Color.WHITE); 8 paint.setAntiAlias(true); 9 setFocusable(true); 10 for (int i = 0; i < fishBmp.length; i++) { 11 fishBmp[i] = BitmapFactory.decodeResource(this.getResources(), R.drawable.fish0 + i); 12 } 13 } 14 15 @Override 16 public void surfaceChanged(SurfaceHolder holder, int format, int width, 17 int height) { 18 // TODO Auto-generated method stub 19 20 } 21 22 @Override 23 public void surfaceCreated(SurfaceHolder holder) { 24 // TODO Auto-generated method stub 25 bmp = BitmapFactory.decodeResource(this.getResources(), R.drawable.water); 26 x = -bmp.getWidth() + this.getWidth(); 27 //Log.v("chendd", "bmp:"+bmp.getWidth() ); 28 //Log.v("chendd", "this:"+this.getWidth() ); 29 y = this.getHeight() - bmp.getHeight(); 30 flag = true; 31 //实例线程 32 th = new Thread(this); 33 //启动线程 34 th.start(); 35 //Mydraw(); 36 } 37 38 private void Mydraw() { 39 // TODO Auto-generated method stub 40 try { 41 canvas = sfh.lockCanvas(); 42 if (canvas != null) { 43 canvas.drawColor(Color.WHITE); 44 canvas.drawBitmap(bmp, x, y, new Paint()); 45 canvas.drawBitmap(fishBmp[currentFrame], this.getWidth()/2, this.getHeight()-60, paint); 46 } 47 } catch (Exception e) { 48 // TODO: handle exception 49 } finally { 50 if (canvas != null) 51 sfh.unlockCanvasAndPost(canvas); 52 } 53 } 54 55 @Override 56 public void surfaceDestroyed(SurfaceHolder holder) { 57 // TODO Auto-generated method stub 58 59 } 60 61 62 @Override 63 public boolean onTouchEvent(MotionEvent event) { 64 // TODO Auto-generated method stub 65 Mydraw(); 66 return true; 67 } 68 69 @Override 70 public void run() { 71 // TODO Auto-generated method stub 72 while (flag) { 73 long start = System.currentTimeMillis(); 74 Mydraw(); 75 logic(); 76 long end = System.currentTimeMillis(); 77 try { 78 if (end - start < 10) { 79 Thread.sleep(10 - (end - start)); 80 } 81 } catch (InterruptedException e) { 82 e.printStackTrace(); 83 } 84 } 85 } 86 87 private void logic() { 88 // TODO Auto-generated method stub 89 //Log.v("chendd", "x:"+x ); 90 if(x == (-bmp.getWidth()/2 + this.getWidth())){ 91 x = -bmp.getWidth() + this.getWidth(); 92 }else { 93 x+=1; 94 } 95 currentFrame++; 96 if (currentFrame >= fishBmp.length) { 97 currentFrame = 0; 98 } 99 100 }