1 .计算机表示图形的几种方式
png :以高质量保存,用于网络
jpg :以良好执行保存 用于计算机 网络
bmp格式 无损 没有经过压缩 是以高质量保存 用于计算机或者网站
图片大小计算公式:图片的总像素 * 每个像素的大小
单色 : 最多可以表示2种颜色 要么是黑要么是白色,只需要使用长度为1 的二进制位来表示 那么一个像素占1/8byte
16色 :最多可以表示16种颜色 0-15 0000-1111,那么只需要使用长度为4的二进制位来表示 ,那么一个像素占1/2byte
256色.每个像素最多可以表示256种颜色, 0-255 ,0000 0000- 1111 1111 那么只需要使用长度为8的二进制为来表示 那么一个像素占1byte
24位图.最多可以表示1600多万种颜色,
r 0 -255
g 0-255
b 0-255 一共一个像素占3byte
Android中表示颜色 A 1
R 1
G 1
B 1 一个像素占4byte
2.Android中加载大图片
07-14 01:37:42.471: E/AndroidRuntime(2295): Caused by: java.lang.OutOfMemoryError 内存溢出
07-14 01:37:42.441: I/dalvikvm-heap(2295): Forcing collection of SoftReferences for 30720012-byte allocation 30720000
如何解决oom ?可以压缩显示图片 需要动态计算缩放比
[1]获取图片分辨率 2400*3200
[2]获取手机的分辨率 320 * 480
[3]计算缩放比 7 6 按照大的去缩
实现步骤
1)获取手机的分辨率
1.WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
2. //[2]获取手机的分辨率
3. int width = wm.getDefaultDisplay().getWidth();
4. int height = wm.getDefaultDisplay().getHeight();
2)获取图片的宽和高
1.BitmapFactory.Options options = new Options();
2.
3. options.inJustDecodeBounds = true;//解码器不去真正解析位图,但是还可以获取图片的宽高信息
4. BitmapFactory.decodeFile(“mnt/sdcard/dog.jpg”,options);
5.
6. //[4]获取图片的宽和高
7. int imgWidth = options.outWidth;
8. int imgHeight = options.outHeight;
9. System.out.println(“图片的宽:”+imgWidth+”~~~~”+imgHeight);
3)计算缩放比 安装我们计算出来的缩放比 去加载图片
1.//[5]计算图片的缩放比
2. int scale = 1; //代表缩放比
3. int scaleX = imgWidth / width;
4. int scaleY = imgHeight / height;
5. if (scaleX >= scaleY && scaleX > scale) {
6. scale = scaleX;
7. }
8. if (scaleY > scaleX && scaleY > scale) {
9. scale = scaleY;
10. }
11. System.out.println(“缩放比为:”+scale);
12.
13. //[6]按照我们计算出来的缩放比去加载图片
14. options.inSampleSize = scale;
15. //[7]去真正的解析位图 安装我们计算出来的缩放比
16. options.inJustDecodeBounds = false;
17. Bitmap bitmap = BitmapFactory.decodeFile(“mnt/sdcard/dog.jpg”,options);
18.
19. //[8]把bitmap展示到控件上
20. iv.setImageBitmap(bitmap);
3 创建原图的副本
- //[2]把srcBitmap 拷贝一份 展示到iv_copy上 相当于你创建了一个原图的模板 这个模板是空的是没有任何内容的 有了一张白纸
- Bitmap copyBitmap = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), srcBitmap.getConfig());
- //[2.1]想作画需要一个画笔
- Paint paint = new Paint();
- //[2.2]想作画 的创建一个画布 把白纸铺到了画布上
- Canvas canvas = new Canvas(copyBitmap);
- //[2.3]就可以参考原图去作画 白纸上就画上了内容
canvas.drawBitmap(srcBitmap, new Matrix(), paint);
为什么要创建原图的副本 因为原图不可以被修改
4 对图片实现特殊的效果
[1]旋转
matrix.setRotate(30,srcBitmap.getWidth()/2,srcBitmap.getHeight()/2);
[2]缩放
matrix.setScale(0.5f, 0.5f);
[3]位移
matrix.setTranslate(20, 0);
[4]镜面
matrix.setScale(-1.0f,1.0f);
matrix.postTranslate(srcBitmap.getWidth(), 0);
[5]倒影
matrix.setScale(1.0f,-1.0f);
matrix.postTranslate(0, srcBitmap.getHeight());
实际开发中使用动画 去实现上面的效果
5画画板案例
1.
2.
3. private Canvas canvas;
4. private Paint paint;
5. private Bitmap copyBitmap;
6. private Bitmap srcBitmap;
7. private ImageView iv;
8.
9. @Override
10. protected void onCreate(Bundle savedInstanceState) {
11. super.onCreate(savedInstanceState);
12. setContentView(R.layout.activity_main);
13.
14. iv = (ImageView) findViewById(R.id.iv);
15. // 获取原图
16. srcBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.bg);
17. // 相当于是一个白纸
18. copyBitmap = Bitmap.createBitmap(srcBitmap.getWidth(),srcBitmap.getHeight(), srcBitmap.getConfig());
19. // 创建画笔
20. paint = new Paint();
21. // 创建画布
22. canvas = new Canvas(copyBitmap);
23. // [2.3]参考原图去作画
24. canvas.drawBitmap(srcBitmap, new Matrix(), paint);
25. // canvas.drawLine(30, 40, 70, 90, paint);
26.
27. iv.setImageBitmap(copyBitmap);
28.
29. // [2.4]给iv设置触摸事件
30. iv.setOnTouchListener(new OnTouchListener() {
31. float startX = 0;
32. float startY = 0;
33.
34. @Override
35. public boolean onTouch(View v, MotionEvent event) {
36. // 具体判断一下到底是什么触摸事件
37. int action = event.getAction(); // 获取手指触摸的事件类型
38. switch (action) {
39. case MotionEvent.ACTION_DOWN: // 按下
40. // 获取到手指按下的坐标
41. startX = event.getX();
42. startY = event.getY();
43.
44. System.out.println(“按下:startX” + startX + “—” + startY);
45.
46. break;
47. case MotionEvent.ACTION_MOVE: // 移动
48.
49. float stopX = event.getX();
50. float stopY = event.getY();
51. System.out.println(“stopX:” + stopX + “—-” + stopY);
52. canvas.drawLine(startX, startY, stopX, stopY, paint);
53.
54. // 把画的内容展示到iv上
55. iv.setImageBitmap(copyBitmap);
56.
57. // 改变一下开始坐标
58. startX = stopX;
59. startY = stopY;
60.
61. break;
62. case MotionEvent.ACTION_UP:// 抬起
63.
64. break;
65. }
66.
67. return true; // 监听器会把当前事件给消费掉
68. }
69. });
70.
71. }
72.
73. //点击按钮把画笔颜色变成红色
74. public void click1(View v) {
75.
76. paint.setColor(Color.RED);
77. }
78.
79. //点击按钮 把画笔加粗
80. public void click2(View v) {
81.
82. //设置画笔的宽度
83. paint.setStrokeWidth(20);
84. }
85.
86. //点击按钮把大作 保存起来
87. public void click3(View v) {
88.
89. //format 照片的格式 quality质量
90. try {
91. File file = new File(Environment.getExternalStorageDirectory().getPath(),”dazuo.png”);
92. FileOutputStream fos = new FileOutputStream(file);
93. copyBitmap.compress(CompressFormat.PNG, 100, fos);
94. fos.close();
95. } catch (Exception e) {
96. e.printStackTrace();
97. }
98.
99.
100. }
6撕衣服 idea 手电筒
1.
2.
3. @Override
4. protected void onCreate(Bundle savedInstanceState) {
5. super.onCreate(savedInstanceState);
6. setContentView(R.layout.activity_main);
7.
8. final ImageView iv = (ImageView) findViewById(R.id.iv);
9.
10. // [1]先获取原图
11. Bitmap srcBitmap = BitmapFactory.decodeResource(getResources(),
12. R.drawable.pre19);
13.
14. // [2]创建原图的副本 相当于你有了一张白纸
15. final Bitmap copyBitmap = Bitmap.createBitmap(srcBitmap.getWidth(),srcBitmap.getHeight(), srcBitmap.getConfig());
16. Paint paint = new Paint();
17. // 把白纸铺到画布上
18. Canvas canvas = new Canvas(copyBitmap);
19. canvas.drawBitmap(srcBitmap, new Matrix(), paint);
20.
21. // [3]把copybitmap展示到iv上
22. iv.setImageBitmap(copyBitmap);
23. // [4]给iv设置触摸事件
24. iv.setOnTouchListener(new OnTouchListener() {
25.
26. @Override
27. public boolean onTouch(View v, MotionEvent event) {
28. switch (event.getAction()) {
29.
30.
31. case MotionEvent.ACTION_MOVE: //移动
32. //手指滑动让图片变透明
33.
34. for (int i = 0; i < 15; i++) { //增加x
35. for (int j = 0; j < 15; j++) { //增加y的值
36. //为了良好的用户体验 加上一句话 撕一个圆
37. if (Math.sqrt(i*i+j*j)<15) {
38. try {
39. copyBitmap.setPixel((int)event.getX()+i, (int)event.getY()+j, Color.TRANSPARENT);
40. } catch (Exception e) {
41.
42. }
43. }
44.
45.
46. }
47.
48. }
49.
50.
51. //更新一下图片
52. iv.setImageBitmap(copyBitmap);
53.
54. break;
55.
56.
57. }
58.
59. return true;
60. }
61. });
62.
63. }
小细节:模拟器是4.1.2 没有问题 如果你创建的模拟器版本是2.3模拟器 一撕就撕出来的是黑色
7 播放音乐
mediaplayer : 用于播放音频或者是视频
1.try {
2. //[1]创建mediaplayer实例
3. MediaPlayer mediaPlayer = new MediaPlayer();
4. //[2]xpg.mp3在sd卡放着 设置播放资源 path:可以是本地路径也可以是网络路径
5. mediaPlayer.setDataSource(“/mnt/sdcard/xpg.mp3”);
6. //[3]准备播放
7. mediaPlayer.prepare();
8. //[4]开始播放
9. mediaPlayer.start();
10. } catch (Exception e) {
11. e.printStackTrace();
12. }
8 mediaplayer的生命周期
播放网络音乐 使用下面的api
1.
2. try {
3. //[1]创建mediaplayer实例
4. final MediaPlayer mediaPlayer = new MediaPlayer();
5. //[2]xpg.mp3在sd卡放着 设置播放资源 path:可以是本地路径也可以是网络路径
6. mediaPlayer.setDataSource(“http://192.168.81.94:8080/xpg.mp3“);
7. //[3]准备播放
8.// mediaPlayer.prepare(); //播放本地音乐一般使用这个方法 同步 张三喊李四吃饭 张三一直喊李四
9. //[3.1]
10. mediaPlayer.prepareAsync();//播放网络音乐使用 异步 张三喊李四吃饭
11.
12. //[3.2]设置一个准备完成的监听
13. mediaPlayer.setOnPreparedListener(new OnPreparedListener() {
14. //这个方法执行了 说明xmp.mp3数据缓冲好了
15. @Override
16. public void onPrepared(MediaPlayer mp) {
17. //[4]开始播放
18. mediaPlayer.start();
19. }
20. });
21.
22.
23. } catch (Exception e) {
24. e.printStackTrace();
25. }
26.
9 播放视频
和播放音频的区别
(1)播放视频需要一个控件把播放的内容展示出来
(2)surfaceView 控件 他是一个重量级 button textview.....
这个控件内部维护了2个线程 A ------B
B -------A 也可以直接在子线程更新Ui
1.
2.
3. private MediaPlayer mediaPlayer;
4. private int currentPosition; //这个变量的意思是 当前视频播放的位置
5. @Override
6. protected void onCreate(Bundle savedInstanceState) {
7. super.onCreate(savedInstanceState);
8. setContentView(R.layout.activity_main);
9.
10.
11. SurfaceView sfView = (SurfaceView) findViewById(R.id.sfv);
12.
13. //[0]获取 SurfaceHolder
14. SurfaceHolder holder = sfView.getHolder();
15.
16. //[0.1]通过holder生命周期来维护视频的播放
17. holder.addCallback(new Callback() {
18.
19. //当surfaceview销毁
20. @Override
21. public void surfaceDestroyed(SurfaceHolder holder) {
22.
23. System.out.println(“surfaceDestroyed 销毁”);
24. //当surfaceview销毁的时候 停止播放视频 获取到当前视频播放的位置
25. if (mediaPlayer!=null&&mediaPlayer.isPlaying()) {
26. //获取视频播放的位置
27.
28. currentPosition = mediaPlayer.getCurrentPosition();
29.
30. //把视频停止
31. mediaPlayer.stop();
32. }
33.
34.
35. }
36.
37. //当surfaceview 初始化了
38. @Override
39. public void surfaceCreated(SurfaceHolder holder) {
40.
41. //在这个方法里面去播放视频
42. try {
43. //[1]创建mediaplayer实例
44. mediaPlayer = new MediaPlayer();
45. //[2]xpg.mp3在sd卡放着 设置播放资源 path:可以是本地路径也可以是网络路径
46. mediaPlayer.setDataSource(“http://192.168.81.94:8080/cc.mp4“);
47. //[3]
48. mediaPlayer.prepareAsync();//播放网络音乐使用 异步 张三喊李四吃饭
49.
50. //[3.1]设置视频的播放内容 SurfaceHolder:是用来维护视频播放的内容 通过serviceview获取实例
51.
52. mediaPlayer.setDisplay(holder);
53.
54.
55. //[4]设置一个准备完成的监听
56. mediaPlayer.setOnPreparedListener(new OnPreparedListener() {
57. //这个方法执行了 说明xmp.mp3数据缓冲好了
58. @Override
59. public void onPrepared(MediaPlayer mp) {
60. //[4]开始播放
61. mediaPlayer.start();
62.
63. //[5]继续上次的位置继续播放
64. mediaPlayer.seekTo(currentPosition);
65.
66. }
67. });
68.
69.
70. } catch (Exception e) {
71. e.printStackTrace();
72. }
73.
74. }
75.
76. @Override
77. public void surfaceChanged(SurfaceHolder holder, int format, int width,
78. int height) {
79.
80. }
81. });
82.
83.
84.
85.
86.
87.
88. }
89.
90.
10 videoView 专门用来播放视频
1.//[1]找到控件
2. VideoView vv = (VideoView) findViewById(R.id.vv);
3. //[2]设置视频播放的路径
4. vv.setVideoPath(“http://192.168.81.94:8080/cc.mp4“);
5. //[3]播放
6. vv.start();
7.
是mediaplayer和surfaceview的一个封装
注意: mediaplayer播放视频只支持mp4 或者3gp格式 avi格式
11 vitamio开源项目的使用
类库 是以完整Android的工程形式提供 就可以当作是一个jar包使用
使用步骤
-
- 1 引入vitamio框架 以library、
-
- 2 在布局中定义VideoView