十、多媒体编程

什么是多媒体?

多种媒体的综合。图片、音乐、视频。

1. 计算机表示图形的方式

(1)bmp 以高质量保存所有类型的图片,用于计算机。

计算机使用像素点表示图形,每个像素点都是一个颜色,24位深度(24bit)。
每个像素点的颜色是一个RGB,使用6个十六进制的数值来表示。
文件头信息占用的数据大小。  体积比较大。

(2)jpg 以良好的质量保存图片,用于计算机、电子邮件或网络。

jpg 工业图形的压缩算法,类似rar的算法。人眼识别精度有限,把相邻空间内类似的颜色使用同一个颜色来表示。 体积减小,失真。

(3)png 203.2k 255*340 以高质量保存图片或者绘图,用于计算机或网络。

2. 加载大图片的OOM异常

java.lang.OutOfMemoryError :

堆内存空间:给类实例、数组分配内存空间的。

RGB ARGB 32

应用程序在启动时系统为它创建一个进程,系统为每个进程创建dalvik虚拟机(模拟器设置的VM Heap),当图片的大小大于虚拟机的堆内存空间时,就内存溢出(内存泄露);

解决办法:缩放图片加载到内存

步骤:

1、获得设备屏幕的分辨率;
2、得到原图的分辨率;
3、通过比较得到一个合适的比例值;
4、按照比例值缩放图片
5、把图片显示在imageview

代码:

package com.lile.loadbigpic;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.os.Bundle;
import android.os.Environment;
import android.view.Display;    
import android.view.WindowManager;
import android.widget.ImageView;

public class MainActivity extends Activity {

    private ImageView iv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        iv = (ImageView) findViewById(R.id.iv);

        // 1、获得设备屏幕的分辨率;
        // 通过服务获得窗口管理器
        WindowManager wm =  (WindowManager) getSystemService(WINDOW_SERVICE);
        // 获得设备分辨率对象
        Display display = wm.getDefaultDisplay();

        // api13之前使用这个两个方法,13之后置为过期
        int screenWidth = display.getWidth();
        int screenHeight = display.getHeight();

        // 2、得到原图的分辨率;
        Options opts = new Options();
        opts.inJustDecodeBounds = true;
        // opts为null 可以返回一个图片对象,如果不为null ,就会返回null
        BitmapFactory.decodeFile(Environment.getExternalStorageDirectory()+"/lp.jpg", opts);
        // 得到原图的宽和高
        int srcWidth = opts.outWidth;
        int srcHeight = opts.outHeight;

        // 3、通过比较得到一个合适的比例值;
        // 3000/320 = 9 2262/480 =5
        int sx = srcWidth/screenWidth;
        int sy = srcHeight/screenHeight;
        int scale = 0;
        if(sx >= 1 && sx > sy){
            scale = sx;
        } else if(sy >= 1 && sy > sx) {
             scale = sy;
        }

        // 4、按照比例值缩放图片
        opts.inJustDecodeBounds = false;
        opts.inSampleSize = scale; // 1/scale * 1/scale
        Bitmap bm = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory()+"/lp.jpg", opts);

        // 5、把图片显示在imageview
        iv.setImageBitmap(bm);
    }
}

3_在内存中创建原图的副本(重点)

步骤:

1、得到原图;
2、创建一个空白的纸张,参考原图;
3、创建一个画板,参考空白纸张;
4、创建一个画笔;
5、在画板上画画;

代码:

package com.lile.copypic;

import android.app.Activity;
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.widget.ImageView;

    public class MainActivity extends Activity {

    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 srcPic = BitmapFactory.decodeResource(getResources(), R.drawable.meinv);

        // config 包括位深度
        // 2、创建一个空白的纸张,参考原图;
        Bitmap copyPic = Bitmap.createBitmap(srcPic.getWidth(), srcPic.getHeight(), srcPic.getConfig());    

        // 3、创建一个画板,参考空白纸张;
        Canvas canvas = new Canvas(copyPic);

        // 4、创建一个画笔;
        Paint paint = new Paint();
        paint.setColor(Color.BLACK);//默认是使用黑色,后面会根据原图的颜色画画

        // 5、在画板上画画;
        canvas.drawBitmap(srcPic, new Matrix(), paint);

        iv.setImageBitmap(copyPic);
    }
}

4_计算机图形处理的API(重点)

* 旋转
* 缩放
* 平移
* 镜面、倒影
* 修改颜色
ColorMatrix cm = new ColorMatrix();
cm.set(new float[] {
        1, 0, 0, 0, 0, // red
        0, 1, 0, 0, 0, // green
        0, 0, 1, 0, 0, // blue
        0, 0, 0, 1, 0  // 透明度
});
paint.setColorFilter(new ColorMatrixColorFilter(cm));

5. 微信画画板

package com.itheima.painter;

import android.app.Activity;
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.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;

public class MainActivity extends Activity {

    private ImageView iv;
    private Bitmap srcPic;
    private Bitmap copyPic;
    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);

        srcPic = BitmapFactory.decodeResource(getResources(), R.drawable.bg);

        copyPic = Bitmap.createBitmap(srcPic.getWidth(), srcPic.getHeight(), srcPic.getConfig());
        canvas = new Canvas(copyPic);

        paint = new Paint();
        // 默认是使用黑色,后面会根据原图的颜色画画
        paint.setColor(Color.BLACK);
        // 5、在画板上画画;
        Matrix matrix = new Matrix();

        canvas.drawBitmap(srcPic, matrix, paint);
        iv.setImageBitmap(copyPic);
        iv.setOnTouchListener(new OnTouchListener(){
            int startX ;
            int startY;
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                int type = event.getAction();

                switch (type) {
                    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();

                    canvas.drawLine(startX, startY, newX, newY, paint);
                    iv.setImageBitmap(copyPic);

                    // 得到新的开始坐标点
                    startX = (int) event.getX();
                    startY = (int) event.getY();
                    break;
                }

                // 消费掉当前的监听器
                return true;
            }

        });

    }
}

6. 视频播放器videoview(重点)

package com.lile.videoview;

import android.app.Activity;
import android.os.Bundle;
import android.widget.VideoView;

public class MainActivity extends Activity {

    private VideoView vv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        vv = (VideoView) findViewById(R.id.vv);
        vv.setVideoPath("http://192.168.22.136:8080/11.mp4");
        vv.start();
    }
}

7. 视频播放器surfaceview(重点)

surfaceview表面视图

双缓冲区:使用两个线程协调工作;

surfaceview 重量级空间,当画面可见时,双缓冲器被创建,占用较高的cpu和内存资源。
当界面不可见时,双缓冲器占用释放。

8.音乐播放器API

package com.itheima.surfaceview;

import android.app.Activity;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnPreparedListener;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;

public class MainActivity extends Activity {

    private SurfaceView sv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        sv = (SurfaceView) findViewById(R.id.sv);

        SurfaceHolder holder = sv.getHolder();
        // 推送缓冲数据,api 13之前的版本上必须执行这行代码,13版本之后,播放器可以自动把
        // 数据加载到缓冲区
        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

        holder.addCallback(new Callback() {

            private MediaPlayer mediaPlay;

            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                try {
                    mediaPlay = new MediaPlayer();

                    mediaPlay.setDataSource("http://192.168.22.136:8080/11.mp4");
                    mediaPlay.setAudioStreamType(AudioManager.STREAM_MUSIC);

                    mediaPlay.setDisplay(holder);

                    // 使用阻塞式准备方法,等待数据资源准备完成后才开始播放,用于播放本地的音视频文件
//                  mediaPlay.prepare(); 
                    // 使用异步式准备方法,使用子线程等待数据资源准备完成后才开始播放,用于播放网络上的音视频文件
                    mediaPlay.prepareAsync();

                    mediaPlay.setOnPreparedListener(new OnPreparedListener() {

                        @Override
                        public void onPrepared(MediaPlayer mp) {
                            mediaPlay.start();
                        }
                    });
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
                if(mediaPlay != null && mediaPlay.isPlaying()){
                    mediaPlay.stop();
                    mediaPlay.release();
                    mediaPlay = null;
//                  mediaPlay.seekTo(msec);
                }
            }


            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width,
                    int height) {
                // TODO Auto-generated method stub

            }
        });
    }
}

9. vitamio框架的使用

(1)引入vitamio框架 以library、

(2)在布局中定义VideoView

<io.vov.vitamio.widget.VideoView 
    android:id="@+id/vv"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    />

(3)mainactivity代码
插件vitamio框架检查是否可用

if (!LibsChecker.checkVitamioLibs(this)) {
    return;
}

final VideoView vv = (VideoView) findViewById(R.id.vv);
vv.setVideoPath("http://192.168.1.2:8080/haha.avi");
vv.setOnPreparedListener(new OnPreparedListener() {

    @Override
    public void onPrepared(MediaPlayer mp) {
        vv.start();

    }
});

// 设置video的控制器
vv.setMediaController(new MediaController(this));

(4)一定要在清单文件初始化InitActivity

<activity android:name="io.vov.vitamio.activity.InitActivity"></activity>

10. 照相机拍照

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 
file = new File(Environment.getExternalStorageDirectory()+"/123.jpg");
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
startActivityForResult(intent, 0);

11. 录机应用

Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); 
file = new File(Environment.getExternalStorageDirectory()+"/123.3gp");
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
startActivityForResult(intent, 0);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值