1 计算机表示图形的几种方式
bmp:以高质量保存,用于计算机
jpg:以良好的质量保存,用于计算机和网络
png:以高质量保存
bmp格式图片大小的计算方式:图片的总像素*每个像素的大小
【1】单色:每个像素最多可以表示2种颜色,要么是黑,要么是白,那么只需要使用长度为1的二进制位来表示,那么一个像素占1/8个byte
【2】16色:每个像素最多可以表示16种颜色,0000-1111,那么只需要使用长度为4的二进制位表示,那么一个像素占4/8 = 1/2个byte
【3】256色:每个像素最多可以表示256种颜色,00000000-11111111,那么只需要使用长度为8的二进制位来表示,那么一个像素占1个byte
【4】24位:每个像素最多可以表示1600多万中颜色,RGB的组合,那么一个像素占用3个byte,R:占1个byte G:占1个byte B:占1个byte
Android中采用的是png格式,Android中采用ARGB格式,其中A代表透明度,Android中一个像素占4个byte
2 缩放加载大图片
09-11 21:20:22.080:I/dalvikvm-heap(2041):Forcing collection of SoftReferences for 30720012-byte allocation(申请这么大的空间,与图片实际大小没多大关系,与图片的像素有关系)
【1】获取图片分辨率 3120*4160
【2】获取手机分辨率 320*480
【3】计算缩放比 (宽除以宽,高除以高) 宽的缩放比为9.75,高的缩放比为8.667 (一般小数点后面的省略)
所以 宽:9 宽正好
高:8 高正好
实现步骤:
【1】获取手机分辨率
//[1]获取手机的分辨率 windowmanager smsManager TelephyManager
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
//过时的方法获取分辨率
int height = wm.getDefaultDisplay().getHeight();//获取高
int width = wm.getDefaultDisplay().getWidth();//获取宽
System.out.println("width:"+width+"-----"+height);
//新的方法获取分辨率
// Point point = new Point();
// wm.getDefaultDisplay().getSize(point);
// int width = point.x;
// int height = point.y;
// System.out.println("width:"+width+"-----"+height);
【2】获取图片分辨率
//创建一个位图工厂的配置参数
BitmapFactory.Options options = new Options();
//解码器不会真正解析位图,但是还能够提取图片的宽和高信息
options.inJustDecodeBounds = true;
//有时候会因为你图片太大而报错:AndroidRuntime(2041):Cause by:java.lang.OutOfMemoryError
BitmapFactory.decodeFile("/mnt/sdcard/picture.jpg",options);
//[2]获取图片的宽和高信息
int imgWidth = options.outWidth;
int imgHeight = options.outHeight;
System.out.println("imgWidth:"+imgWidth+"----"+imgHeight);
【3】计算缩放比
//[3]计算缩放比
int scale = 1;
int scaleX = imgWidth/width;
int scaleY = imgHeight/height;
if (scaleX > scaleY && scaleX > scale) {
scale = scaleX;
}if (scaleY > scaleX && scaleY > scale) {
scale = scaleY;
}
System.out.println("缩放比:"+scale);
【4】按照缩放比进行显示
//[4]按照缩放比进行显示
options.inSampleSize = scale;
//[5]按照缩放比进行解析位图
options.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeFile("/mnt/sdcard/picture.jpg",options);
//[6]把bitmap显示到iv上
iv.setImageBitmap(bitmap);
注意:[1]真实手机是改不了 dvm 分配的内存大小
[2]缩放加载大图片,就是加载分辨率特别大的图片
3 创建原图的副本
为什么要创建原图的副本?因为原图不可以修改!
//显示原图
ImageView iv_src = (ImageView) findViewById(R.id.iv_src);
//显示副本
ImageView iv_copy = (ImageView) findViewById(R.id.iv_copy);
//[1]先把tomcat.png图片转换成bitmap 显示到iv_src
Bitmap srcBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.tomcat);
//[1.1]操作图片
//srcBitmap.setPixel(20, 30, Color.RED);
iv_src.setImageBitmap(srcBitmap);
//[2]创建原图的副本
//[2.1]创建一个模板 相当于创建了一个大小和原图一样的空白白纸
Bitmap copyBitmap = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), srcBitmap.getConfig());
//[2.2]想作画 需要画笔
Paint paint = new Paint();
//[2.3]创建一个画布 把白纸铺到画布上
Canvas canvas = new Canvas(copyBitmap);
//[2.4]开始作画
canvas.drawBitmap(srcBitmap, new Matrix(), paint);
//[2.5]操作画出来的小猫照片
for (int i = 0; i < 20; i++) {
copyBitmap.setPixel(20+i, 30, Color.RED);
}
0
//[3]把copybitmap显示到iv_copy上
iv_copy.setImageBitmap(copyBitmap);
}
4 图形处理的API
旋转:
matrix.setRotate(20, srcBitmap.getWidth()/2, srcBitmap.getHeight()/2);
缩放:
matrix.setScale(0.5f, 0.5f);
平移:
matrix.setTranslate(30, 0);
镜面:
就是使用缩放和平移的一个组合
matrix.setScale(-1.0f, 1);
//postTranslate方法是上一次修改的基础上进行再次修改 setTranslate方法每次操作都是最新的,会覆盖上次的操作
matrix.postTranslate(srcBitmap.getWidth(), 0);
倒影:
matrix.setScale(1.0f, -1.0f);
matrix.postTranslate(0, srcBitmap.getHeight());
5 画画板小案例
也要先创建原图的副本,然后给iv设置一个触摸事件
iv.setOnTouchListener(new OnTouchListener() {
int startX = 0;
int startY = 0;
@Override
public boolean onTouch(View view, MotionEvent event) {
//获取当前事件的类型
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN://按下
System.out.println("按下");
//获取开始位置(划线)
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上
iv.setImageBitmap(copyBitmap);
//更新一下开始坐标和结束坐标
startX = stopX;
startY = stopY;
break;
case MotionEvent.ACTION_UP://抬起
System.out.println("抬起");
break;
}
//True if the listener has consumes the event,false otherwise
return true;//true:监听器处理完事件了
}
});
可以设置一个按钮,将画保存起来
public void click3(View v){
/*
* format:格式 保存图片的格式
* quality:保存图片的质量
* SystemClock.uptimeMillis():当前手机的开机时间
* */
try {
File file = new File(Environment.getExternalStorageDirectory().getPath(),SystemClock.uptimeMillis()+".png");
FileOutputStream 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();
}
}
6 使用MediaPlayer播放音频文件
//点击按钮 播放一个音频文件
public void click(View v){
//[1]初始化MediaPlayer
MediaPlayer mediaPlayer = new MediaPlayer();
//[2]设置要播放的资源位置 path可以是网络资源 也可以是本地资源
try {
mediaPlayer.setDataSource("/mnt/sdcard/xpg.mp3");
//[3]准备播放
mediaPlayer.prepare();
//[4]开始播放
mediaPlayer.start();
} catch (Exception e) {
e.printStackTrace();
}
}
7 MediaPlayer的生命周期
同步和异步
同步准备:一般播放本地音乐
异步准备:一般播放网络音乐,不用开子线程
8 SurfaceView介绍
播放视频
MediaPlayer只能播放mp4格式或者3gp格式
surfaceView它是一个重量级应用
内部维护了2个线程
A线程 加载数据 A负责显示
B线程 负责显示 B去加载数据
它可以直接在子线程中更新UI
9 VideoView控件介绍
VideoView是对SurfaceView和MediaPlayer的封装
AVI格式或者rmvb格式
布局里面:
<VideoView
android:id="@+id/vv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
//[1]找到控件
VideoView vv = (VideoView) findViewById(R.id.vv);
//[2]设置播放的路径
vv.setVideoPath("http://192.168.177.1:8080/miss.mp4");
vv.start();
10 vitamio框架
解码原理:使用的是一个开源项目
11照相机和录像机
//点击按钮 实现拍照
public void click1(View v){
// create Intent to take a picture and return control to the calling application
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File file = new File(Environment.getExternalStorageDirectory().getPath(),"haha.png");
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file)); // 保存图片
// start the image capture Intent
startActivityForResult(intent, 1);
}
//当开启的Activity关闭的时候调用
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
System.out.println("onActivityResult");
super.onActivityResult(requestCode, resultCode, data);
}
//点击按钮 实现录影
public void click2(View v){
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
File file = new File(Environment.getExternalStorageDirectory().getPath(),"hehe.mp4");
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file)); // 保存图片
// start the image capture Intent
startActivityForResult(intent, 2);
}