day10 多媒体(文字 图片 音频 视频)
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);
}
}
只言片语任我说,提笔句句无需忖。落笔不知寄何人,唯有邀友共斟酌。