8

Android调用系统相机、自定义相机、处理大图片

 3 years ago
source link: https://renyugang.blog.csdn.net/article/details/38947637
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Android调用系统相机、自定义相机、处理大图片

Android调用系统相机和自定义相机实例


本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显示出来,该例子也会涉及到Android加载大图片时候的处理(避免OOM),还有简要提一下有些人SurfaceView出现黑屏的原因。

Android应用拍照的两种方式,下面为两种形式的Demo展示出来的效果。

 

20140830222353378
  
20140830222116671

一、调用系统自带的相机应用

二、自定义我们自己的拍照界面

三、关于计算机解析图片原理(如何正确加载图片到Android应用中)

所需权限:

一、调用系统照相机程序拍照(方式一)


1.定义所需要的权限
2.我们需要定义调用系统相机App的Intent,当然是通过设定IntentFilter中的Action来打开我们想要的activity了。


MediaStore.ACTION_IMAGE_CAPTURE - 这个Action将打开拍照的系统相机。返回一个Image


MediaStore.ACTION_VIDEO_CAPTURE - 这个Action将打开录像的系统相机。返回一个Video


在MediaStore.ACTION_IMAGE_CAPTURE中,我们可以看到这段话:


【The caller may pass an extra EXTRA_OUTPUT to control where this image will be 


written. If the EXTRA_OUTPUT is not present, then a small sized image is returned 


as a Bitmap object in the extra field. This is useful for applications that only 


need a small image. If the EXTRA_OUTPUT is present, then the full-sized image will 


be written to the Uri value of EXTRA_OUTPUT.】

3.API规定我们传入拍照得到图片的存储位置的Uri。否则Bimmap将以一个压缩后的形式返回到我们当前Activity.


intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); // set the image file name

则会把拍照的图片存储到我们传入的Uri对应的File里面。

4.我们调用startActivityForResult(intent)来启动这样一个系统相机app之后,然后在当前应用Activity的onActivityResult()中接受到返回拍照成功或者失败的消息,做相应处理。


5.“压缩处理”(Android应用中加载大图片),并显示到ImageView中。


二、自定义照相机

1.检查相机是否存在,并获取相机Camera。

2.创建一个相机图像预览类:extends SurfaceView 并 implements SurfaceHolder (我定义:MySurfaceView)
3.把这个预览类放入一个自定义布局layout里面,并且可以在layout里添加自己的其他按钮
4.设置对应的拍照按钮然后听事件
5.捕获照片和保存图片

6.释放掉我们使用的相机Camera,不然之后其他应用将无法使用它。

三、计算机解析图片的方式和Android中大图片Bitmap的压缩显示处理

这个问题有点老生长谈了,平时我们经常遇到一些图片资源,我们把它加载到内存发现抛出内存不够用的异常,即OOM,当然加载图片时出现的OOM情况有很多种,比如单张图片没有做压缩,导致图片占用内存过大而发生内存溢出,也有多张图片一次性加载进来,导致的内存溢出。

通常单张大图,我们加载进来往往会经过一个图片的压缩处理的过程,而如果多张图片加载,我们可能就需要一些缓存机制,再加上一些算法来保证程序不出现OOM。

我们这里想要讲的知识点跟单张大图比较有关系

首先,我们知道一个图片,它是由很多像素点来表示的,而像素点的个数只跟图片的分辨率有关,而跟图片所占的内存空间大小无关。比如我们的桌面壁纸:1280 * 768 的分辨率,那么它就有 1280 * 768 = 983040个像素点,这意味着什么呢?我们知道我们要表示一个像素点的颜色,最经常我们需要RGB三种颜色来表示,而R:0~255,相当于两个FF的位置,就是8位,这样的话RGB合起来,一个像素点的表示就需要24位(这就是我们平衡听到的24位图),而加上透明度的8位,就是平时说的32位图。那么一张图片,它加载到内存中的话,它会占用多大的空间呢?

计算方法:(像素点 * 一个像素所占用的byte数) / 1024 / 1024 (MB) 

以1280 * 768 的分辨率,32位图为例:所占内存大小: ((1280 * 768 * (32 / 8)) / 1024)/1024=3.75(MB)

说了这么多,那么我们再来说下Android系统的规定吧,Android系统严格规定了每个应用所能分配的最大的内存为多少,我们知道有一个VM值(在我们创建模拟器的时候),这个VM值里面便是我们所说的堆空间(Heap Size),当你的应用占用的空间已经超出我们定义的堆空间大小,那么不好意思,OOM

这样的话,我们明白了图片的大小占据原理,还有尽量不要超出这个堆空间,那么OK,现在问题变得简单了。如果我们有一种方式可以在图片加载进来之前,知道图片的大小,然后改变它的长、宽,这样的话,分辨率便变小了,这样出来的乘积也就变小了。比如:我们的屏幕只有320 * 240, 这时候你加载大分辨的图片进来最多也只能显示成这样,所以我们常采用的是对图片进行压缩处理。这里有个概念叫压缩比:

长:1024 / 320 = 3.2  约等于 3

宽:768 / 240 = 3.2 

那这样我们如果把图片压缩成这样大小的,最后的图片加载进来的大小便是

((320 * 240 * (32 / 8)) / 1024)/1024=0.29(MB)

希望我这样讲完,大家都能听懂了,我这里先把照相机实例中出现的关于如果处理这块图片的代码先粘出来

关于堆空间:

堆(HEAP)是VM中占用内存最多的部分,通常是动态分配的。堆的大小不是一成不变的,通常有一个分配机制来控制它的大小。比如初始的HEAP是4M大,当4M的空间被占用超过75%的时候,重新分配堆为8M大;当8M被占用超过75%,分配堆为16M大。倒过来,当16M的堆利用不足30%的时候,缩减它的大小为8M大。重新设置堆的大小,尤其是压缩,一般会涉及到内存的拷贝,所以变更堆的大小对效率有不良影响。

废话少说下面就看代码咯~~为了大家看起来方便点,代码的结构可能不是很规范!

源码下载地址:http://download.csdn.net/detail/u011133213/7844683

代码部分: 

一、用系统的相机

按钮点击之后开启系统相机Activity

生成File文件,并得到Uri

二、用自定义的相机

检测相机设备是否存在:

按钮按下之后的判断:

自定义的SurfaceView类:

自定义相机Activity类:(为了避免当用户按下Home键,之后再回到我们App中,SurfaceView变黑屏,我们需要将SurfaceView加载到FrameLayout中的代码写在onResume中)


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK