当前位置:网站首页>安德鲁斯—-多媒体编程
安德鲁斯—-多媒体编程
2022-07-06 18:48:00 【全栈程序员站长】
大家好,又见面了,我是全栈君
多媒体概念
- 写作、图画、音频、视频 计算计算机图像尺寸 图像大小 = 图像总像素 * 每个像素的大小占据
- 单色图:每一个像素占用1/8个字节
- 16色图:每一个像素占用1/2个字节
- 256色图:每一个像素占用1个字节
- 24位图:每一个像素占用3个字节
载入大图片到内存
Android系统以ARGB表示每一个像素,所以每一个像素占用4个字节,非常easy内存溢出
对图片进行缩放
- 获取屏幕宽高
Display dp = getWindowManager().getDefaultDisplay();
int screenWidth = dp.getWidth();
int screenHeight = dp.getHeight();
- 获取图片宽高
Options opts = new Options();
//请求图片属性但不申请内存
opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile("sdcard/dog.jpg", opts);
int imageWidth = opts.outWidth;
int imageHeight = opts.outHeight;
- 图片的宽高除以屏幕宽高,算出宽和高的缩放比例,取较大值作为图片的缩放比例
int scale = 1;
int scaleX = imageWidth / screenWidth;
int scaleY = imageHeight / screenHeight;
if(scaleX >= scaleY && scaleX > 1){
scale = scaleX;
}
else if(scaleY > scaleX && scaleY > 1){
scale = scaleY;
}
- 按缩放比例载入图片
//设置缩放比例
opts.inSampleSize = scale;
//为图片申请内存
opts.inJustDecodeBounds = false;
Bitmap bm = BitmapFactory.decodeFile("sdcard/dog.jpg", opts);
iv.setImageBitmap(bm);
在内存中创建图片的副本
直接载入的bitmap对象是仅仅读的。无法改动。要改动图片仅仅能在内存中创建出一个一模一样的bitmap副本。然后改动副本
//载入原图
Bitmap srcBm = BitmapFactory.decodeFile("sdcard/photo3.jpg");
iv_src.setImageBitmap(srcBm);
//创建与原图大小一致的空白bitmap
Bitmap copyBm = Bitmap.createBitmap(srcBm.getWidth(), srcBm.getHeight(), srcBm.getConfig());
//定义画笔
Paint paint = new Paint();
//把纸铺在画版上
Canvas canvas = new Canvas(copyBm);
//把srcBm的内容绘制在copyBm上
canvas.drawBitmap(srcBm, new Matrix(), paint);
iv_copy.setImageBitmap(copyBm);
在内存中创建图片的副本 直接载入的bitmap对象是仅仅读的。无法改动。要改动图片仅仅能在内存中创建出一个一模一样的bitmap副本。然后改动副本
//载入原图
Bitmap srcBm = BitmapFactory.decodeFile("sdcard/photo3.jpg");
iv_src.setImageBitmap(srcBm);
//创建与原图大小一致的空白bitmap
Bitmap copyBm = Bitmap.createBitmap(srcBm.getWidth(), srcBm.getHeight(), srcBm.getConfig());
//定义画笔
Paint paint = new Paint();
//把纸铺在画版上
Canvas canvas = new Canvas(copyBm);
//把srcBm的内容绘制在copyBm上
canvas.drawBitmap(srcBm, new Matrix(), paint);
iv_copy.setImageBitmap(copyBm);
对图片进行特效处理
- 首先定义一个矩阵对象
Matrix mt = new Matrix();
- 缩放效果
//x轴缩放1倍,y轴缩放0.5倍
mt.setScale(1, 0.5f);
- 旋转效果
//以copyBm.getWidth() / 2, copyBm.getHeight() / 2点为轴点,顺时旋转30度
mt.setRotate(30, copyBm.getWidth() / 2, copyBm.getHeight() / 2);
- 平移
//x轴坐标+10,y轴坐标+20
mt.setTranslate(10, 20);
- 镜面
//把X坐标都变成负数
mt.setScale(-1, 1);
//图片总体向右移
mt.postTranslate(copyBm.getWidth(), 0);
- 倒影
//把Y坐标都变成负数
mt.setScale(1, -1);
//图片总体向下移
mt.postTranslate(0, copyBm.getHeight());
画画板
记录用户触摸事件的XY坐标,绘制直线
- 给ImageView设置触摸侦听,得到用户的触摸事件,并获知用户触摸ImageView的坐标
iv.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
switch (event.getAction()) {
//触摸屏幕
case MotionEvent.ACTION_DOWN:
//得到触摸屏幕时手指的坐标
startX = (int) event.getX();
startY = (int) event.getY();
break;
//在屏幕上滑动
case MotionEvent.ACTION_MOVE:
//用户滑动手指。坐标不断的改变,获取最新坐标
int newX = (int) event.getX();
int newY = (int) event.getY();
//用上次onTouch方法得到的坐标和本次得到的坐标绘制直线
canvas.drawLine(startX, startY, newX, newY, paint);
iv.setImageBitmap(copyBm);
startX = newX;
startY = newY;
break;
}
return true;
}
});
- 刷子效果,加粗画笔
paint.setStrokeWidth(8);
- 调色板。改变画笔颜色
paint.setColor(Color.GREEN);
- 保存图片至SD卡
FileOutputStream fos = null;
try {
fos = new FileOutputStream(new File("sdcard/dazuo.png"));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//保存图片
copyBm.compress(CompressFormat.PNG, 100, fos);
- 系统每次收到SD卡就绪广播时。都会去遍历sd卡的全部文件和目录,把遍历到的全部多媒体文件都在MediaStore数据库保存一个索引。这个索引包括多媒体文件的文件名称、路径、大小
- 图库每次打开时。并不会去遍历sd卡获取图片。而是通过内容提供者从MediaStore数据库中获取图片的信息,然后读取该图片
- 系统开机或者点击载入sd卡button时,系统会发送sd卡就绪广播,我们也能够手动发送就绪广播
Intent intent = new Intent();
intent.setAction(Intent.ACTION_MEDIA_MOUNTED);
intent.setData(Uri.fromFile(Environment.getExternalStorageDirectory()));
sendBroadcast(intent);
撕衣服
- 原理:把穿内衣和穿外衣的照片重叠显示。内衣照在以下,用户滑动屏幕时。触摸的是外衣照。把手指经过的像素都置为透明。内衣照就显示出来了
iv.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
int newX = (int) event.getX();
int newY = (int) event.getY();
//把指定的像素变成透明
copyBm.setPixel(newX, newY, Color.TRANSPARENT);
iv.setImageBitmap(copyBm);
break;
}
return true;
}
});
- 每次仅仅设置一个像素点太慢,以触摸的像素为圆心。半径为5画圆,圆内的像素所有置为透明
for (int i = -5; i < 6; i++) {
for (int j = -5; j < 6; j++) {
if(Math.sqrt(i * i + j * j) <= 5)
copyBm.setPixel(newX + i, newY + j, Color.TRANSPARENT);
}
}
音乐播放器
播放服务
- 播放音频的代码应该执行在服务中。定义一个播放服务MusicService
- 服务里定义play、stop、pause、continuePlay等方法
private void play() {
// TODO Auto-generated method stub
player.reset();
try {
player.setDataSource("sdcard/bzj.mp3");
player.prepare();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
player.start();
}
private void pause() {
player.pause();
}
private void stop() {
player.stop();
}
private void continuePlay() {
player.start();
}
- 把这几个方法抽取成一个接口MusicInterface
- 定义一个中间人类,继承Binder,实现MusicInterface
- 先start启动MusicService,再bind
Intent intent = new Intent(this, MusicService.class);
startService(intent);
bindService(intent, conn, BIND_AUTO_CREATE);
- 依据播放进度设置进度条
- 获取当前的播放时间和当前音频的最长时间
int currentPosition = player.getCurrentPosition();
int duration = player.getDuration();
- 播放进度须要不停的获取。不停的刷新进度条。使用计时器每500毫秒获取一次播放进度
- 发消息至Handler。把播放进度放进Message对象中,在Handler中更新SeekBar的进度
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
int currentPosition = player.getCurrentPosition();
int duration = player.getDuration();
Message msg = Message.obtain();
//把播放进度存入Message中
Bundle data = new Bundle();
data.putInt("currentPosition", currentPosition);
data.putInt("duration", duration);
msg.setData(data);
MainActivity.handler.sendMessage(msg);
}
}, 5, 500);
- 在Activity中定义Handler
static Handler handler = new Handler(){
public void handleMessage(android.os.Message msg) {
//取出消息携带的数据
Bundle data = msg.getData();
int currentPosition = data.getInt("currentPosition");
int duration = data.getInt("duration");
//设置播放进度
sb.setMax(duration);
sb.setProgress(currentPosition);
};
};
- 拖动进度条改变播放进度
//给sb设置一个拖动侦听
sb.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
//停止拖动时调用
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
int progress = seekBar.getProgress();
mi.seekTo(progress);
}
//開始拖动时调用
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
//拖动的时候不断调用
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub
}
});
视频播放器
SurfaceView
- 对画面的实时更新要求较高
- 双缓冲技术:内存中有两个画布,A画布显示至屏幕,B画布在内存中绘制下一帧画面。绘制完成后B显示至屏幕,A在内存中继续绘制下一帧画面
- 播放视频也是用MediaPlayer。只是跟音频不同,要设置显示在哪个SurfaceView
SurfaceView sv = (SurfaceView) findViewById(R.id.sv);
SurfaceHolder sh = sv.getHolder();
MediaPlayer player = new MediaPlayer();
player.reset();
try {
player.setDataSource("sdcard/2.3gp");
player.setDisplay(sh);
player.prepare();
} catch (Exception e) {
e.printStackTrace();
}
player.start();
- SurfaceView是重量级组件,可见时才会创建
- 给SurfaceHolder设置CallBack。类似于侦听。能够知道SurfaceView的状态
sh.addCallback(new Callback() {
//SurfaceView销毁时调用
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
//SurfaceView创建时调用
@Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
});
- SurfaceView一旦不可见。就会被销毁,一旦可见。就会被创建。销毁时停止播放。再次创建时再開始播放
摄像头
- 启动系统提供的拍照程序
//隐式启动系统提供的拍照Activity
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//设置照片的保存路径
File file = new File(Environment.getExternalStorageDirectory(), "haha.jpg");
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
startActivityForResult(intent, 0);
- 启动系统提供的摄像程序
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
File file = new File(Environment.getExternalStorageDirectory(), "haha.3gp");
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
//设置保存视频文件的质量
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
startActivityForResult(intent, 0);
版权声明:本文博主原创文章,博客,未经同意不得转载。
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/116865.html原文链接:https://javaforall.cn
边栏推荐
- Ali yunyili: how does yunyuansheng solve the problem of reducing costs and improving efficiency?
- GEE升级,可以实现一件run tasks
- 阿里云易立:云原生如何破解企业降本提效难题?
- Schedulx v1.4.0 and SaaS versions are released, and you can experience the advanced functions of cost reduction and efficiency increase for free!
- Integerset of PostgreSQL
- Argo workflows source code analysis
- Compress JS code with terser
- ODBC database connection of MFC windows programming [147] (with source code)
- [C # notes] reading and writing of the contents of text files
- STM32项目 -- 选题分享(部分)
猜你喜欢
A new path for enterprise mid Platform Construction -- low code platform
【森城市】GIS数据漫谈(二)
Zhang Ping'an: accelerate cloud digital innovation and jointly build an industrial smart ecosystem
Go swagger use
15million employees are easy to manage, and the cloud native database gaussdb makes HR office more efficient
Integerset of PostgreSQL
The boss is quarantined
张平安:加快云上数字创新,共建产业智慧生态
Tiflash source code reading (IV) design and implementation analysis of tiflash DDL module
新一代云原生消息队列(一)
随机推荐
The cities research center of New York University recruits master of science and postdoctoral students
Douban average 9 x. Five God books in the distributed field!
【论文阅读|深读】DNGR:Deep Neural Networks for Learning Graph Representations
C#/VB. Net to delete watermarks in word documents
[paper reading | deep reading] anrl: attributed network representation learning via deep neural networks
Lumion 11.0 software installation package download and installation tutorial
Collection recommandée!! Quel plug - in de gestion d'état flutter est le plus fort? Regardez le classement des manons de l'île, s'il vous plaît!
postgresql之整體查詢大致過程
Compress JS code with terser
The empirical asset pricing package (EAP) can be installed through pypi
Stm32f4 --- PWM output
Decryption function calculates "task state and lifecycle management" of asynchronous task capability
1个月增长900w+播放!总结B站顶流恰饭的2个新趋势
New generation cloud native message queue (I)
How do I dump SoapClient requests for debugging- How to dump SoapClient request for debug?
SchedulX V1.4.0及SaaS版发布,免费体验降本增效高级功能!
FLIR blackfly s industrial camera: explanation and configuration of color correction and code setting method
FLIR blackfly s usb3 industrial camera: how to use counters and timers
Sensor: DS1302 clock chip and driver code
3 -- Xintang nuc980 kernel supports JFFS2, JFFS2 file system production, kernel mount JFFS2, uboot network port settings, and uboot supports TFTP