%title multi-meida
%toc
图片, 音频, 视频, 摄像头
= 图片 =
== 加载大图片到内存 ==
我们创建虚拟机时, 默认给每个应用分配的内存大小是16Mb, (VM Heap 16Mb).
如果我们加载大图片时, 很可能导致内存溢出.
但是我们会发现, 即使加载的图片只有2-3Mb, 也会溢出, 这是为什么?
位图图像加载到内存中时, 是采用数组来存放数据的. 一个图片其本身可能不是很大,
但是在内存中想要表示这张图片, 需要一个二维数组, 数组大小为图片宽X高(像素数),
这还没完, 一个数组元素大小要包含RGBA四个分量, 即4byte, 这样一乘, 就很大了.
如果我们想要加载大图片, 就要进行缩放, 需要下面几步:
# 获取屏幕的宽高
# 获取图片的宽高
# 获取水平缩放比例和垂直缩放比例
# 使用二者中较大的值对图片进行缩放
代码如下:
{ { {class="brush:java"
public class MainActivity extends Activity {
private ImageView iv;
private int windowWidth ;
private int windowHeight ;
@SuppressWarnings("deprecation")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv = (ImageView) findViewById(R.id.iv);
//1. 获取手机屏幕的分辨率 宽高
Display display = getWindowManager().getDefaultDisplay();
// 下面的方法虽然过时了, 但是还是很经常用
windowWidth = display.getWidth();
windowHeight = display.getHeight();
// Point p = new Point();
// display.getSize(p);
// p.x; p.y;
System.out.println("窗体的宽度:"+windowWidth);
System.out.println("窗体的高度:"+windowHeight);
}
public void click(View view){
// 创建解析器选项
Options opts = new Options();
// 设置解析器 不去真正的解析这个位图 而是解析这个图片的out输出信息,(宽度 高度)
// 不会为图片的每个点 申请内存空间
opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile("/sdcard/IMG_0017.JPG", opts);
// 得到图像的宽高
int picHeight = opts.outHeight;
int picWidth = opts.outWidth;
int scaleX = picWidth / windowWidth;
int scaleY = picHeight / windowHeight;
int scale = 1;
if(scaleX>scaleY && scaleY >1){
//按照水平缩放
scale = scaleX;
}
if(scaleY>scaleX && scaleX >1){
//按照竖直平缩放
scale = scaleY;
}
// 真正的解析这个位图
opts.inJustDecodeBounds = false;
// 设置缩放比例
opts.inSampleSize = scale;
Bitmap bitmap = BitmapFactory.decodeFile("/sdcard/IMG_0017.JPG",opts);
iv.setImageBitmap(bitmap);
}
}
}}}
== 图像的exif信息 ==
ExifInterface exif = new ExifInterface("/sdcard/IMG_0017.JPG");
System.out.println(exif.getAttribute(ExifInterface.TAG_DATETIME));
== 从图库选择图片 ==
这个比较简单, 我们只需要开启系统图库应用的activity, 让其返回数据即可.
{ { {class="brush:java"
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);
}
public void click(View view){
Intent intent = new Intent();
intent.setAction("android.intent.action.PICK");
intent.addCategory("android.intent.category.DEFAULT");
intent.setType("image/*");
startActivityForResult(intent, 0);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(data!=null){
Uri uri = data.getData();
try {
// 所有uri相关的操作都可以交给 ContentResolver
InputStream is = getContentResolver().openInputStream(uri);
Options opts = new Options();
opts.inSampleSize = 8;
Bitmap bitmap = BitmapFactory.decodeStream(is, new Rect(), opts);
iv.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
super.onActivityResult(requestCode, resultCode, data);
}
}
}}}
== 创建图像的内存拷贝 ==
在应用中, 我们经常会需要对一个图片进行处理, 如旋转, 缩放, 平移等等,
我们不能拿着一个图片的原图进行处理, 而是要创建一个原图的拷贝, 对这个拷贝的图像
进行处理. 下面的代码演示了如何创建图像的内存拷贝
{ { {class="brush:java"
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (data != null) {
Uri uri = data.getData();
iv_src.setImageURI(uri);
try {
InputStream is = getContentResolver().openInputStream(uri);
//创建一个原图的拷贝, 把拷贝的图片 放在iv_dest
//原图对应的bitmap 注意:这个图片是只读的 不可以被修改.
Bitmap bitmap = BitmapFactory.decodeStream(is);
//创建一个可以被修改的位图资源,宽高信息 和 图片的类型 跟原图是一模一样
//下面的代码创建的图片 是一个空白的图片
Bitmap alterBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());
// 拿着可以被修改的图片创建一个画布, 之后画的东西就要画在这块画布上了.
Canvas canvas = new Canvas(alterBitmap);
// 创建一个画笔, 可以拿着它画东西
Paint paint = new Paint();
//创建图形的拷贝, 其实就是把原图按照 Matrix 定义的信息滑到之前的画布上.
canvas.drawBitmap(bitmap, new Matrix(), paint);
// 再往上面写点字
paint.setColor(Color.BLACK);
canvas.drawText("美女", 10, 10, paint);
iv_dest.setImageBitmap(alterBitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
super.onActivityResult(requestCode, resultCode, data);
}
}
}}}
== 图像的简单处理 ==
有了图像的内存拷贝, 我们就可以方便的对图像进行处理了.
1. 缩放
{ { {class="brush:java"
// 创建一个bitmap, 作为可以修改的图像, 为什么这里要搞成这个大小?
// 这将是我们创建的画布的大小, 无论图像怎么缩放, 画布就是这么大
Bitmap alterBitmap = Bitmap.createBitmap(bitmap.getWidth()/2,
(int)(bitmap.getHeight()*1.2), bitmap.getConfig());
//拿着可以被修改的图片创建一个画布.
Canvas canvas = new Canvas(alterBitmap);
Paint paint = new Paint();
// Matrix 是一个坐标矩阵, 可以用来指定图像每个点的坐标计算方式
// matrix有一个计算公式, 参看图形学ppt
Matrix matrix = new Matrix();
// 这些参数是 X, Y , Z 轴
/*matrix.setValues(new float[] {
0.5f, 0, 0,
0, 1.2f, 0,
0, 0, 1
});*/
// 简单的方法设置缩放量, x轴, y轴
matrix.setScale(0.5f, 1.2f);
// 把原图按照设定好的 matrix 画到画布上
canvas.drawBitmap(bitmap, matrix, paint);
}}}
2. 旋转
{ { {class="brush:java"
// 为什么宽度要加60? 旋转后图片可能超出原来的范围了, 所以要加宽一点.
Bitmap alterBitmap = Bitmap.createBitmap(bitmap.getWidth()+60, bitmap.getHeight(), bitmap.getConfig());
Canvas canvas = new Canvas(alterBitmap);
Paint paint = new Paint();
paint.setAntiAlias(true);
Matrix matrix = new Matrix();
// 第一个参数指定旋转角度, 后面两个参数指定旋转中心
matrix.setRotate(30, bitmap.getWidth()/2, bitmap.getHeight()/2);
canvas.drawBitmap(bitmap, matrix, paint);
}}}
3. 平移
{ { {class="brush:java"
Bitmap alterBitmap = Bitmap.createBitmap(bitmap.getWidth()+60, bitmap.getHeight(), bitmap.getConfig());
Canvas canvas = new Canvas(alterBitmap);
Paint paint = new Paint();
paint.setAntiAlias(true);
Matrix matrix = new Matrix();
// 设置偏移量, 第一个为x轴, 第二个为y轴
matrix.postTranslate(20, 0);
canvas.drawBitmap(bitmap, matrix, paint);
}}}
4. 镜面
{ { {class="brush:java"
Bitmap alterBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());
Canvas canvas = new Canvas(alterBitmap);
Paint paint = new Paint();
paint.setAntiAlias(true);
Matrix matrix = new Matrix();
// 如果想让x轴变为负的, 第一个参数给-1, 算是缩放的另一种形式吧
matrix.setScale(-1, 1);
// x轴变成负的后, 还要在平移回来, 要不就看不见了.
matrix.postTranslate(bitmap.getWidth(),0);
canvas.drawBitmap(bitmap, matrix, paint);
}}}
5. 倒影
{ { {class="brush:java"
Bitmap alterBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());
Canvas canvas = new Canvas(alterBitmap);
Paint paint = new Paint();
paint.setAntiAlias(true);
Matrix matrix = new Matrix();
// y轴变成负的即可
matrix.setScale(1, -1);
matrix.postTranslate(0,bitmap.getHeight());
canvas.drawBitmap(bitmap, matrix, paint);
}}}
谷歌: www.google.ie or www.google.fr
搜索: 图像处理 filetype:ppt
== 扒掉美女的衣服 ==
== 处理图片的颜色 ==
图像的位移, 旋转等需要的是 坐标矩阵, 修改图像的颜色则需要修改图片的颜色矩阵.
{ { {class="brush:java"
alterBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());
canvas = new Canvas(alterBitmap);
paint = new Paint();
paint.setAntiAlias(true);
Matrix matrix = new Matrix();
// 创建一个颜色矩阵, 这些参数为 R, G, B, A
ColorMatrix cm = new ColorMatrix();
// 把红色调成两倍
cm.set(new float[] {
2, 0, 0, 0, 0,
0, 1, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 1, 0
});
paint.setColorFilter(new ColorMatrixColorFilter(cm));
canvas.drawBitmap(bitmap, matrix, paint);
}}}
== 图片合成/人脸识别 ==
face++
-------------------------------
SeekBar 是 ProgressBar 的子类
-------------
自己写个音乐播放器
多线程断线下载, 重写一遍
-------------