位图是我们开发中最常用的资源, 毕竟一个漂亮的界面对用户是最有吸引力的, 那么怎样获 取位图,获取位图时该注意哪些,接下来 eoe 给大家仔细讲解。
一、从资源中获取位图
可以使用 BitmapDrawable 或者 BitmapFactory 来获取资源中的位图。 当然,首先需要获取资源:
1. Resources res=getRes
ources(); 复制代码
使用 BitmapDrawable 获取位图:
1. 2. 使用 BitmapDrawable (InputStream is)构造一个 BitmapDrawable; 使用 BitmapDrawable 类的 getBitmap()获取得到位图;
1. // 读取 InputStream 并得到位图 2. 3. InputStream is=res.openRawResource(R.drawable.pic180); 4. 5. BitmapDrawable bmpDraw=new BitmapDrawable(is); 6. 7. Bitmap bmp=bmpDraw.getBitmap(); 复制代码
或者采用下面的方式:
1. BitmapDrawable bmpDraw=(BitmapDrawable)res.getDrawable(R.drawable.pic180); 2. 3. 复制代码 Bitmap bmp=bmpDraw.getBitmap();
使用 BitmapFactory 获取位图: (Creates Bitmap objects from various sources, including files, streams, and byte-arrays.) 使用 BitmapFactory 类 decodeStream(InputStream is)解码位图资源,获取位图。
1. Bitmap bmp=BitmapFactory.decodeResource(res, R.drawable.pic180); 复制代码
BitmapFactory 的所有函数都是 static,这个辅助类可以通过资源 ID、路径、文件、数据流 等方式来获取位图。 以上方法在编程的时候可以自由选择,在 Android SDK 中说明可以支持的图片格式如下:
png (preferred), jpg (acceptable), gif (discouraged),和 bmp(Android SDK Support Media Format)。 二. 获取位图的信息 要获取位图信息,比如位图大小、像素、density、透明度、颜色格式等,获取得到 Bitmap 就迎刃而解了,这些信息在 Bitmap 的手册中,这里只是辅助说明以下 2 点: (1) Bitmap 中对 RGB 颜色格式使用 Bitmap.Config 定义, 仅包括 ALPHA_8、 ARGB_4444、 ARGB_8888、RGB_565,缺少了一些其他的,比如说 RGB_555,在开发中可能需要注意这 个小问题; (2)Bitmap 还提供了 compress()接口来压缩图片,不过 AndroidSAK 只支持 PNG、JPG 格 式的压缩;其他格式的需要 Android 开发人员自己补充了。 三. 显示位图 显示位图可以使用核心类 Canvas,通过 Canvas 类的 drawBirmap()显示位图,或者借助于 BitmapDrawable 来将 Bitmap 绘制到 Canvas。当然,也可以通过 BitmapDrawable 将位图 显示到 View 中。 转换为 BitmapDrawable 对象显示位图:
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 复制代码 iv2.setImageDrawable(bmpDraw); ImageView iv2 = (ImageView)findViewById(R.id.ImageView02); // 显示位图 BitmapDrawable bmpDraw=new BitmapDrawable(bmp); // 转换为 BitmapDrawable 对象 Bitmap bmp=BitmapFactory.decodeResource(res, R.drawable.pic180); // 获取位图
使用 Canvas 类显示位图, 这儿采用一个继承自 View 的子类 Panel, 在子类的 OnDraw 中显 示:
1. public class MainActivity extends Activity {
2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.pic180); 26. 27. 28. 29. 30. 31. 32. } canvas.drawBitmap(bmp, 10, 10, null); canvas.drawColor(Color.BLACK); public void onDraw(Canvas canvas){ } super(context); public Panel(Context context) { class Panel extends View{ } setContentView(new Panel(this)); super.onCreate(savedInstanceState); public void onCreate(Bundle savedInstanceState) { @Override /** Called when the activity is first created. */
33. 34. 35. 复制代码
}
}
四. 位图缩放
(1)将一个位图按照需求重画一遍,画后的位图就是我们需要的了,与位图的显示几乎一 样:drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint)。 (2) 在原有位图的基础上, 缩放原位图, 创建一个新的位图: CreateBitmap(Bitmap source, int x, int y, int width, int height, Matrix m, boolean filter) (3)借助 Canvas 的 scale(float sx, float sy) (Preconcat the current matrix with the specified scale.),不过要注意此时整个画布都缩放了。 (4)借助 Matrix:
1. Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.pic180); 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 复制代码 canvas.drawBitmap(dstbmp, 10, 10, null); canvas.drawColor(Color.BLACK); bmp.getHeight(),matrix,true); Bitmap dstbmp=Bitmap.createBitmap(bmp,0,0,bmp.getWidth(), matrix.postScale(0.2f, 0.2f); Matrix matrix=new Matrix();
五. 位图旋转
同样,位图的旋转也可以借助 Matrix 或者 Canvas 来实现。
1. Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.pic180);
2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 复制代码 canvas.drawBitmap(dstbmp, 10, 10, null); canvas.drawColor(Color.BLACK); bmp.getHeight(),matrix,true); Bitmap dstbmp=Bitmap.createBitmap(bmp,0,0,bmp.getWidth(), matrix.postRotate(45); matrix.postScale(0.8f, 0.8f); Matrix matrix=new Matrix();
旋转效果:
六.图片水印的生成方法 图片水印的生成方法 生成水印的过程。其实分为三个环节:第一,载入原始图片;第二,载入水印图片;第三, 保存新的图片。
1. * 2. * create the bitmap from a byte array 3. * 4. * @param src the bitmap object you want proecss 5. * @param watermark the water mark above the src 6. * @return return a bitmap object ,if paramter's length is 0,return null 7. */ 8. private Bitmap createBitmap( Bitmap src, Bitmap watermark ) 9. { 10. String tag = "createBitmap"; 11. Log.d( tag, "create a new bitmap" ); 12. if( src == null ) 13. {
14. 15. } 16.
return null;
17. int w = src.getWidth(); 18. int h = src.getHeight(); 19. int ww = watermark.getWidth(); 20. int wh = watermark.getHeight(); 21. //create the new blank bitmap 22. Bitmap newb = Bitmap.createBitmap( w, h, Config.ARGB_8888 );//创建一个新 的和 SRC 长度宽度一样的位图 23. Canvas cv = new Canvas( newb ); 24. //draw src into 25. cv.drawBitmap( src, 0, 0, null );//在 0,0 坐标开始画入 src 26. //draw watermark into 27. cv.drawBitmap( watermark, w - ww + 5, h - wh + 5, null );//在 src 的右下角 画入水印 28. //save all clip 29. cv.save( Canvas.ALL_SAVE_FLAG );//保存 30. //store 31. cv.restore();//存储 32. return newb; 33. } 复制代码
7.Canvas 的 save 和 restore onDraw 方法会传入一个 Canvas 对象,它是你用来绘制控件视觉界面的画布。 在 onDraw 方法里, 我们经常会看到调用 save 和 restore 方法, 它们到底是干什么用的呢? ? save:用来保存 Canvas 的状态。save 之后,可以调用 Canvas 的平移、放缩、旋转、错 切、裁剪等操作。 ? restore:用来恢复 Canvas 之前保存的状态。防止 save 后对 Canvas 执行的操作对后续 的绘制有影响。 save 和 restore 要配对使用(restore 可以比 save 少,但不能多),如果 restore 调用次数
比 save 多,会引发 Error。save 和 restore 之间,往往夹杂的是对 Canvas 的特殊操作。 例如:我们先想在画布上绘制一个右向的三角箭头,当然,我们可以直接绘制,另外,我们 也可以先把画布旋转 90°,画一个向上的箭头,然后再旋转回来(这种旋转操作对于画圆周 上的标记非常有用)。然后,我们想在右下角有个 20 像素的圆,那么,onDraw 中的核心 代码是:
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 复制代码 canvas.drawCircle(px - 10, py - 10, 10, linePaint); // Draw circle canvas.restore(); canvas.drawLine(px / 2, 0, px / 2, py, linePaint); canvas.drawLine(px / 2, 0, px, py / 2, linePaint); canvas.drawLine(px / 2, 0, 0, py / 2, linePaint); // Draw up arrow canvas.rotate(90, px/2, py/2); canvas.save(); canvas.drawRect(0, 0, px, py, backgroundPaint); // Draw background int py = getMeasuredWidth(); int px = getMeasuredWidth();
效果如图 1 所示:
如果我们不调用 save 和 restore 会是什么样子呢?如图 2 所示:
从这两个图中,我们就能看到圆圈位置的明显差异。不进行 Canvas 的 save 和 restore 操作 的话,所有的图像都是在画布旋转 90°后的画布上绘制的。当执行完 onDraw 方法,系统自 动将画布恢复回来。save 和 restore 操作执行的时机不同,就能造成绘制的图形不同。