day10 多媒体(文字 图片 音频 视频)

2023-05-08,,

1计算机表示图形的几种方式
    bmp:以高质量保存     用于计算机
    jpg:以良好的质量保存    用于计算机或者网络
    png:以高质量保存
    图片大小的计算公式:图片的总像素*每个像素的大小    (多出的一点是图片的信息)
    单色:每个像素最多可以表示2种颜色 要么是黑要么是白 那么只需要使用长度为1的二进制位来表示    那么一个像素占1/8byte
    16色:每个像素最多可以表示16种颜色 0000-1111 那么只需要使用长度为4的二进制位来表示    那么一个像素占1/2byte
    256色:每个像素最多可以表示256种颜色 0000 0000-1111 1111 那么只需要使用长度为8的二进制位来表示    那么一个像素占1byte
    24位:每个像素最多可以表示1600万多种颜色 0000 0000 0000 0000 0000 0000-1111 1111 1111 1111 1111 1111 那么一个像素占3byte   rgb:r----1byte   g----1byte   b----1byte

Android中采用的是png格式    Android中采用ARGB    Android中一个像素占4byte

2缩放加载大图片
[1]获取图片的分辨率
[2]获取手机的分辨率
[3]计算缩放比    用图片的分辨率宽高除以手机分辨率,最后在宽高中选大的
[4]按照大的去缩放

实现步骤:
[1]获取手机分辨率

    // [1]获取手机的分辨率windowmanager WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE); // 获取高 int height = wm.getDefaultDisplay().getHeight(); int width = wm.getDefaultDisplay().getWidth(); System.out.println("width:" + width + " height:" + height);

[2]获取图片的分辨率

    //创建一个位图工厂的配置参数 BitmapFactory.Options options = new Options(); //解码器不去真正的解析位图 但是还能够获取图片的宽和高信息 options.inJustDecodeBounds = true; BitmapFactory.decodeFile("/mnt/sdcard/lings.jpg", options); //[2]获取图片的宽和高信息 int imgWidth = options.outWidth; int imgHeight = options.outHeight;

[3]计算缩放比

    //[3]计算缩放比 int scale = 1; int scaleX = imgWidth/width; int scaleY = imgHeight/height; if(scaleX>=scaleY && scaleX > 1){ scale = scaleX; } if(scaleX<scaleY && scaleY > 1){ scale = scaleY; }

[4]按照缩放比进行显示

    //[4]按照缩放比进行显示 options.inSampleSize = scale; //[5]按照缩放比 进行解析位图 options.inJustDecodeBounds = false; Bitmap bitmap = BitmapFactory.decodeFile("/mnt/sdcard/lings.jpg", options); //[6]把bitmap显示iv上 iv.setImageBitmap(bitmap);

注意:[1]真实手机是改不了 dvm分配的内存大小
          [2]缩放加载大图片    就是加载分辨率特别大的图片

3创建原图的副本

    package com.phone.fuben; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.widget.ImageView; public class MainActivity extends ActionBarActivity { private ImageView iv_src; private ImageView iv_copy; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 显示原图 iv_src = (ImageView) findViewById(R.id.iv_src); // 显示副本 iv_copy = (ImageView) findViewById(R.id.iv_copy); // [1]先把lings.jpg图片转换成bitmap显示到iv_src Bitmap srcBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.lings); // 操作图片 // srcBitmap.setPixel(20, 30, Color.RED); iv_src.setImageBitmap(srcBitmap); // [2]创建原图的副本(模板代码) // 创建一个模板 相当于创建了一个大小和原图一样的空白的白纸 Bitmap copyBitmap = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), srcBitmap.getConfig()); // 想作画需要一个画笔 Paint paint = new Paint(); // 创建一个画布 把白纸铺到画布上 Canvas canvas = new Canvas(copyBitmap); // 开始作画 canvas.drawBitmap(srcBitmap, new Matrix(), paint); // 操作画出来的小猫图片 for (int i = 0; i < 20; i++) { copyBitmap.setPixel(20 + i, 30, Color.RED); } // [3]把copybitmap显示到iv_copy上 iv_copy.setImageBitmap(copyBitmap); } }

4图形处理的api
旋转
缩放
平移
镜面
倒影

    package com.phone.fuben1; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.widget.ImageView; import com.phone.fuben1.R; public class MainActivity extends ActionBarActivity { private ImageView iv_src; private ImageView iv_copy; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 显示原图 iv_src = (ImageView) findViewById(R.id.iv_src); // 显示副本 iv_copy = (ImageView) findViewById(R.id.iv_copy); // [1]先把lings.jpg图片转换成bitmap显示到iv_src Bitmap srcBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.lings); // 操作图片 // srcBitmap.setPixel(20, 30, Color.RED); iv_src.setImageBitmap(srcBitmap); // [2]创建原图的副本(模板代码) // 创建一个模板 相当于创建了一个大小和原图一样的空白的白纸 Bitmap copyBitmap = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), srcBitmap.getConfig()); // 想作画需要一个画笔 Paint paint = new Paint(); // 创建一个画布 把白纸铺到画布上 Canvas canvas = new Canvas(copyBitmap); // 开始作画 Matrix matrix = new Matrix(); // 对图片进行旋转 matrix.setRotate(20, srcBitmap.getWidth() / 2, srcBitmap.getHeight() / 2); // 对图片进行缩放 matrix.setScale(0.5f, 0.5f); // 对图片进行平移 matrix.setTranslate(20, 0); //对图片进行镜面效果 //如果两个方法一起用就要用post前缀,post是在上一次修改的基础上进行再次修改 set每次操作都是最新的 会覆盖上次的操作 matrix.setScale(-1.0f, 1); matrix.postTranslate(srcBitmap.getWidth(), 0); //对图片进行倒影效果 matrix.setScale(1, -1.0f); matrix.postTranslate(0, srcBitmap.getHeight()); canvas.drawBitmap(srcBitmap, matrix, paint); // [3]把copybitmap显示到iv_copy上 iv_copy.setImageBitmap(copyBitmap); } }

5画画板小案例

    package com.phone.painting; import java.io.File; import java.io.FileOutputStream; import android.app.Activity; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.os.SystemClock; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.widget.ImageView; public class MainActivity extends Activity { private Bitmap srcBitmap; private ImageView iv; private Bitmap copyBitmap; private Canvas canvas; private Paint paint; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 用来显示我们画的内容 iv = (ImageView) findViewById(R.id.iv); // [1]获取原图bg srcBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.bg); // [2]获取原图的副本 相当于一个空白的白纸 copyBitmap = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), srcBitmap.getConfig()); paint = new Paint(); canvas = new Canvas(copyBitmap); // 开始作画 canvas.drawBitmap(srcBitmap, new Matrix(), paint); canvas.drawLine(20, 30, 50, 80, paint); iv.setImageBitmap(copyBitmap); // [3]给iv设置一个触摸控件 iv.setOnTouchListener(new OnTouchListener() { private int startX; private int startY; @Override public boolean onTouch(View v, MotionEvent event) { // 获取当前事件类型 int action = event.getAction(); switch (action) { case MotionEvent.ACTION_DOWN:// 按下 System.out.println("摸view"); startX = (int) event.getX(); startY = (int) event.getY(); break; case MotionEvent.ACTION_MOVE:// 移动 System.out.println("移动"); // 获取结束位置 int stopX = (int) event.getX(); int stopY = (int) event.getY(); // 不停的划线 canvas.drawLine(startX, startY, stopX, stopY, paint); // 再次显示到控件上 iv.setImageBitmap(copyBitmap); startX = stopX; startY = stopY; break; case MotionEvent.ACTION_UP:// 抬起 System.out.println("抬起"); break; } // true 监听器处理完事件了 return true; } }); } //点击按钮改变画笔 的颜色 public void click1(View v) { paint.setColor(Color.RED); } //点击按钮加粗画笔 public void click2(View v) { paint.setStrokeWidth(15); } //点击按钮保存图片 public void click3(View v) { try { /** * format 保存图片的格式 * quality 保存图片的质量 * stream */ //SystemClock.uptimeMillis() 当前手机开机时间 File file = new File(Environment.getExternalStorageDirectory().getPath(),SystemClock.uptimeMillis()+".png"); FileOutputStream fos; fos = new FileOutputStream(file); copyBitmap.compress(CompressFormat.PNG, 100, fos); //发送一条广播 欺骗系统图库的应用 Intent intent = new Intent(); //设置action intent.setAction(Intent.ACTION_MEDIA_MOUNTED); intent.setData(Uri.fromFile(Environment.getExternalStorageDirectory())); //发送一下广播 sendBroadcast(intent); } catch (Exception e) { e.printStackTrace(); } } }
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

6撕衣服小案例
    原理:2张图片

    package com.phone.syf; import android.R.integer; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.widget.ImageView; public class MainActivity extends ActionBarActivity { private Bitmap alterBitmap; private ImageView iv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); iv = (ImageView) findViewById(R.id.iv); // [1]获取要操作图片的原图 Bitmap srcBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.lings1); alterBitmap = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), srcBitmap.getConfig()); // 创建画笔 Paint paint = new Paint(); // 创建画布 Canvas canvas = new Canvas(alterBitmap); // 开始作画 canvas.drawBitmap(srcBitmap, new Matrix(), paint); iv.setImageBitmap(alterBitmap); // [3]给iv设置一个触摸事件 iv.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { // [4]具体判断一下触摸事件 switch (event.getAction()) { case MotionEvent.ACTION_MOVE:// 移动事件 for (int x = -7; x < 7; x++) { for (int y = -7; y < 7; y++) { if (Math.sqrt(x * x + y * y) < 7) { try { alterBitmap.setPixel( (int) event.getX() + x, (int) event.getY() + y, Color.TRANSPARENT); } catch (Exception e) { } } } } // 更新一下iv iv.setImageBitmap(alterBitmap); break; } return true; } }); } }

7使用mediaplayer播放音频文件
    [1]这个类用于播放音频或者视频

    package com.phone.videoplayer; import android.app.Activity; import android.media.MediaPlayer; import android.os.Bundle; import android.view.View; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } //点击按钮 播放一个音频文件 public void click(View v){ //[1]初始化mediaplayer MediaPlayer mediaPlayer = new MediaPlayer(); //[2]设置要播放的资源位置 path 可以是网络 路径 也可是本地路径 try { mediaPlayer.setDataSource("/mnt/sdcard/me.mp3"); //[3]准备播放 mediaPlayer.prepare(); //[4]开始播放 mediaPlayer.start(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }

 
8百度音乐盒完善

    package com.phone.baidumusic; import java.util.Timer; import java.util.TimerTask; import android.app.Service; import android.content.Intent; import android.media.MediaPlayer; import android.media.MediaPlayer.OnCompletionListener; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.os.Message; public class MusicService extends Service { private MediaPlayer mediaPlayer; @Override public IBinder onBind(Intent intent) { return new MyBinder(); } @Override public void onCreate() { // [1]初始化mediaplayer mediaPlayer = new MediaPlayer(); super.onCreate(); } @Override public void onDestroy() { super.onDestroy(); } //实现指定播放的位置 public void seekTo(int position){ mediaPlayer.seekTo(position); } // 播放音乐 public void playMusic() { // [2]设置要播放的资源位置 path 可以是网络 路径 也可以是本地路径 try { mediaPlayer.reset(); mediaPlayer.setDataSource("/mnt/sdcard/me.mp3"); // [3]准备播放 mediaPlayer.prepare(); // [4]开始播放 mediaPlayer.start(); // [5]更新进度条 UpdateSeekBar(); } catch (Exception e) { e.printStackTrace(); } System.out.println("音乐播放了"); } // 更新进度条的方法 private void UpdateSeekBar() { //[1]获取到当前播放的总长度 final int duration = mediaPlayer.getDuration(); //[2]使用Timer定时器去定时获取当前进度 final Timer timer = new Timer(); final TimerTask task = new TimerTask() { @Override public void run() { //[1]一秒钟获取一次当前进度 int currentPosition = mediaPlayer.getCurrentPosition(); //[4]拿着我们在mainactivity创建的handler 发消息 消息就可以携带数据 Message msg =Message.obtain(); Bundle data = new Bundle(); data.putInt("duration", duration); data.putInt("currentPosition", currentPosition); msg.setData(data); //发送一条消息 mainactivity里面的handlermessage方法就会执行 MainActivity.handler.sendMessage(msg); } }; //100毫秒后每隔1秒执行一次run方法 timer.schedule(task, 100, 1000); //当歌曲执行完毕后 把timer和timertask取消 mediaPlayer.setOnCompletionListener(new OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { System.out.println("歌曲播放完成了"); //把timer和timertask取消 timer.cancel(); task.cancel(); } }); } // 暂停音乐 public void pauseMusic() { mediaPlayer.pause(); System.out.println("音乐暂停了"); } // 继续播放音乐 public void rePlayMusic() { mediaPlayer.start(); System.out.println("音乐继续播放了"); } // [1]在服务的内部定义一个中间对象(IBinder) private class MyBinder extends Binder implements IService { @Override public void callPlayMusic() { playMusic(); } @Override public void callPauseMusic() { pauseMusic(); } @Override public void callRePlayMusic() { rePlayMusic(); } @Override public void callSeekTo(int position) { seekTo(position); } } }
    package com.phone.baidumusic; import android.app.Activity; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.view.View; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; public class MainActivity extends Activity { //中间人对象 private IService iService; private MyConn conn; private static SeekBar sbar; public static Handler handler = new Handler(){ public void handleMessage(android.os.Message msg) { //获取我们携带的数据 Bundle data = msg.getData(); int duration = data.getInt("duration"); int currentPosition = data.getInt("currentPosition"); //设置seekbar的进度 sbar.setMax(duration); sbar.setProgress(currentPosition); }; }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //混合方式开启服务 //[1]先调用startservice 目的是可以保证服务在后台长期运行 Intent intent = new Intent(this, MusicService.class); startService(intent); //[2]调用bindservice 目的为了获取我们定义的中间人对象 就可以间接的调用服务里面的方法了 conn = new MyConn(); bindService(intent, conn, BIND_AUTO_CREATE); //[3]找到seekbar 设置进度 sbar = (SeekBar) findViewById(R.id.seekBar1); //[4]给seekbar设置监听事件 sbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { //当拖动停止的时候调用 @Override public void onStopTrackingTouch(SeekBar seekBar) { iService.callSeekTo(seekBar.getProgress()); } //当开始拖动 @Override public void onStartTrackingTouch(SeekBar seekBar) { } //当进度改变 @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { } }); } @Override protected void onDestroy() { //当Activity销毁的时候 解绑服务 unbindService(conn); super.onDestroy(); } //点击按钮 播放音乐 public void click1(View v){ iService.callPlayMusic(); } //点击按钮 暂停音乐 public void click2(View v){ iService.callPauseMusic(); } //点击按钮 继续播放音乐 public void click3(View v){ iService.callRePlayMusic(); } //监听服务的状态 private class MyConn implements ServiceConnection{ @Override public void onServiceConnected(ComponentName name, IBinder service) { iService = (IService) service; } @Override public void onServiceDisconnected(ComponentName name) { } } }
    package com.phone.baidumusic; public interface IService { public void callPlayMusic(); public void callPauseMusic(); public void callRePlayMusic(); public void callSeekTo(int position); }

9mediaplayer的生命周期
    同步和异步
    同步:一般播放本地音乐    
    异步:播放网络音乐    不用开子线程

    package com.phone.videoplayer; import android.app.Activity; import android.media.MediaPlayer; import android.media.MediaPlayer.OnPreparedListener; import android.os.Bundle; import android.view.View; import com.phone.videoplayeronline.R; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } //点击按钮 播放一个音频文件 public void click(View v){ //[1]初始化mediaplayer final MediaPlayer mediaPlayer = new MediaPlayer(); //[2]设置要播放的资源位置 path 可以是网络 路径 也可是本地路径 try { mediaPlayer.setDataSource("http://192.168.11.86:8080/xpg.mp3"); //[3]准备播放 mediaPlayer.prepareAsync(); //设置一个准备完成的监听 mediaPlayer.setOnPreparedListener(new OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { //开始播放 mediaPlayer.start(); } }); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
    <uses-permission android:name="android.permission.INTERNET"/>

10surfaceview介绍
    播放视频
    mediaplayer    只能播放MP4格式或3gp格式
    surfaceview     是一个重量级控件
                          内部维护了2个线程
                            A    加载数据    A负责显示
                            B    复制显示    b负责去加载数据
                        可以直接在子线程更新UI

11 VideoView控件介绍
    VideoView 是对surfaceView 和 mediaplayer的封装
    avi格式    或者rmvb格式

12 vitamio开源框架(有官网)
  使用步骤:
        [1]引入vitamio框架  引library
        [2]在布局中定义VideoView
            <io.vov.vitamio.widget.VideoView
        android:id="@+id/vv"
        android:layout_width="wrap_content"

android:layout_height="wrap_content"/>
        [3]mainactivity代码

    //使用vitamio //插件vitamio框架检查是否可用 if(!LibsChecker.checkVitamioLibs(this)){ return; } final VideoView vv = (VideoView)findViewById(R.id.vv); vv.setVideoPath("http://192.168.11.86:8080/aa.avi"); vv.setOnPreparedListener(new OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { vv.start(); } }); //设置video的控制器 vv.setMediaController(new MediaController(this));

        [4]一定要在清单文件初始化InitActivity

    <!-- 一定要在清单文件初始化InitActivity --> <activity android:name="io.vov.vitamio.activity.InitActivity"></activity>

    解码原理:使用的是一个开源项目    ffmpeg    

13    照相机和录像机

    package com.phone.camera; import java.io.File; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.provider.MediaStore; import android.support.v7.app.ActionBarActivity; import android.view.View; public class MainActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } //点击按钮进行照相 public void click1(View v) { Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); File file = new File(Environment.getExternalStorageDirectory().getPath(),"ahha.png"); //保存图片的位置 intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file)); startActivityForResult(intent, 1); //发送一条广播 欺骗系统图库的应用 Intent intent1 = new Intent(); //设置action intent.setAction(Intent.ACTION_MEDIA_MOUNTED); intent.setData(Uri.fromFile(Environment.getExternalStorageDirectory())); //发送一下广播 sendBroadcast(intent1); } //当开启的activity关闭的时候调用 @Override protected void onActivityResult(int arg0, int arg1, Intent arg2) { System.out.println("方法执行了"); super.onActivityResult(arg0, arg1, arg2); }
    //点击按钮进行录像 public void click2(View v) { Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); File file = new File(Environment.getExternalStorageDirectory().getPath(),"ahhaA.MP4"); //保存图片的位置 intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file)); startActivityForResult(intent, 2); //发送一条广播 欺骗系统图库的应用 Intent intent1 = new Intent(); //设置action intent.setAction(Intent.ACTION_MEDIA_MOUNTED); intent.setData(Uri.fromFile(Environment.getExternalStorageDirectory())); //发送一下广播 sendBroadcast(intent1); } }

来自为知笔记(Wiz)

day10 多媒体(文字 图片 音频 视频)的相关教程结束。

《day10 多媒体(文字 图片 音频 视频).doc》

下载本文的Word格式文档,以方便收藏与打印。