安卓基础_14

本文介绍Android中图片处理技巧,包括不同格式图片的特点、内存优化方法、创建图片副本及实现特殊效果等。同时,还讲解了多媒体应用开发,如音乐播放、视频播放等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 创建原图的副本

  1. //[2]把srcBitmap 拷贝一份 展示到iv_copy上 相当于你创建了一个原图的模板 这个模板是空的是没有任何内容的 有了一张白纸
  2. Bitmap copyBitmap = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), srcBitmap.getConfig());
  3. //[2.1]想作画需要一个画笔
  4. Paint paint = new Paint();
  5. //[2.2]想作画 的创建一个画布 把白纸铺到了画布上
  6. Canvas canvas = new Canvas(copyBitmap);
  7. //[2.3]就可以参考原图去作画 白纸上就画上了内容
  8. 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. 1 引入vitamio框架 以library、

    1. 2 在布局中定义VideoView
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值