在android 中实现照相机的方式一般有两种

1、调用系统的相机

2、自定义相机

1、调用系统照相机程序拍照

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

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

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

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

intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); // 设置图片地址名称 会把拍照的图片存储到我们传入的Uri对应的File里面。

4.我们调用startActivityForResult(intent)来启动这样一个系统相机app之后,然后在当前应用Activity的onActivityResult()中接受到返回拍照成功或者失败的消息,做相应处理。
5.“压缩处理”(Android应用中加载大图片),并显示到ImageView中。

基本实现:

准备工作:设置 调用相机的回调码 和 设置 调用照相机拍照后保存图片的位置,名称,及后缀名(图片类型)

private int n=3;  private  File sdcardTempFile = new File("/mnt/sdcard/", "tmp_pic_" + SystemClock.currentThreadTimeMillis() + ".jpg");


在button监听器中调用相机:

[java]  view plain  copy  
  1. //调用系统照相机拍照  
  2.     bt4.setOnClickListener(new OnClickListener() {  
  3.   
  4.         @Override  
  5.         public void onClick(View v) {  
  6.             Intent intent=new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);    
  7.             Uri u=Uri.fromFile(sdcardTempFile);   
  8.             intent.putExtra(MediaStore.Images.Media.ORIENTATION, 0);   
  9.             intent.putExtra(MediaStore.EXTRA_OUTPUT, u);   
  10.             intent.putExtra("return-data"true);  
  11.             startActivityForResult(intent, n);   
  12.   
  13.         }  
  14.     });  
[java]  view plain  copy  
  1.   

回调函数中接收图片:

[java]  view plain  copy  
  1. @Override  
  2.     protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
  3.          super.onActivityResult(requestCode, resultCode, data);   
  4.         if (resultCode == RESULT_OK) {  
  5.             System.out.println("requestCode"+requestCode);  
  6.               
  7.             switch (requestCode){  
  8.               
  9.             case 2:  
  10.                  Uri tuku_uri = data.getData();  
  11.                  System.out.println(tuku_uri.getPath());  
  12.                    ContentResolver tuku_cr = this.getContentResolver();  
  13.                    try {  
  14.                     bmp = BitmapFactory.decodeStream(tuku_cr.openInputStream(tuku_uri));  
  15.                         MCShareLaunchShareHelper.shareContentWithBitmap("测试分享本地图片", bmp, "your share url""", MoxunActivity.this);  
  16.                 } catch (FileNotFoundException e) {  
  17.                     // TODO Auto-generated catch block  
  18.                     e.printStackTrace();  
  19.                 }  
  20.                 break;  
  21.             case 3:  
  22.                    try {  
  23.                        Uri uri = Uri.parse(android.provider.MediaStore.Images.Media.insertImage(getContentResolver(), sdcardTempFile.getAbsolutePath(), nullnull));   
  24.                        System.out.println(uri.getPath());  
  25.                        ContentResolver cr = this.getContentResolver();  
  26.                          
  27.                        bmp = BitmapFactory.decodeStream(cr.openInputStream(uri));  
  28.                         MCShareLaunchShareHelper.shareContentWithBitmap("测试照相机图片", bmp, "your share url""", MoxunActivity.this);  
  29.                 } catch (FileNotFoundException e) {  
  30.                     // TODO Auto-generated catch block  
  31.                     e.printStackTrace();  
  32.                 }  
  33. //方法二  
  34. //if (requestCode == MyApp.CAMERA_RECODE) {  
  35. //              try {  
  36. //                  bmp=BitmapFactory.decodeFile(sdcardTempFile.getAbsolutePath());  
  37. //                  img.setImageBitmap(bmp);  
  38. //                  picCount++;  
  39. //              } catch (Exception e) {  
  40. //                  e.printStackTrace();  
  41. //              }  
  42. //  
  43. //              break;  
  44. //          }  
  45. //    }  
  46.   
  47.     }   



2、自定义相机

基本实现方式: 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)


Android提供了Camera来控制拍照,步骤如下:
(1)调用Camera的open()方法打开相机。
(2)调用Camera的getParameters()获取拍照参数,该方法返回一个Cmera.Parameters对象。
(3)调用Camera.Parameters对象对照相的参数进行设置。
(4)调用Camera的setParameters(),并将Camera.Parameters对象作为参数传入,这样就可以对拍照进行参数控制,Android2.3.3以后不用设置。
(5)调用Camerade的startPreview()的方法开始预览取景,在之前需要调用Camera的setPreviewDisplay(SurfaceHolder holder)设置使用哪个SurfaceView来显示取得的图片。
(6)调用Camera的takePicture()方法进行拍照。
(7)程序结束时,要调用Camera的stopPreview()方法停止预览,并且通过Camera.release()来释放资源。

需要赋予Camera的权限:

123
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/><uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/><uses-permission android:name="android.permission.CAMERA"/>

下面上代码:

  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
package com.lyj.camera;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.text.SimpleDateFormat;import java.util.Date;import android.app.Activity;import android.content.pm.ActivityInfo;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.PixelFormat;import android.hardware.Camera;import android.hardware.Camera.AutoFocusCallback;import android.hardware.Camera.CameraInfo;import android.hardware.Camera.Parameters;import android.hardware.Camera.PictureCallback;import android.os.Bundle;import android.view.SurfaceHolder;import android.view.SurfaceView;import android.view.View;import android.view.View.OnClickListener;import android.view.Window;import android.view.WindowManager;import android.widget.ImageButton;import android.widget.ImageView;public class MyCameraActivity extends Activity implements SurfaceHolder.Callback {    private ImageView back, position;//返回和切换前后置摄像头    private SurfaceView surface;    private ImageButton shutter;//快门    private SurfaceHolder holder;    private Camera camera;//声明相机    private String filepath = "";//照片保存路径    private int cameraPosition = 1;//0代表前置摄像头,1代表后置摄像头    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        requestWindowFeature(Window.FEATURE_NO_TITLE);//没有标题        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);//设置全屏        this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);//拍照过程屏幕一直处于高亮        //设置手机屏幕朝向,一共有7种        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);        //SCREEN_ORIENTATION_BEHIND: 继承Activity堆栈中当前Activity下面的那个Activity的方向        //SCREEN_ORIENTATION_LANDSCAPE: 横屏(风景照) ,显示时宽度大于高度         //SCREEN_ORIENTATION_PORTRAIT: 竖屏 (肖像照) , 显示时高度大于宽度         //SCREEN_ORIENTATION_SENSOR  由重力感应器来决定屏幕的朝向,它取决于用户如何持有设备,当设备被旋转时方向会随之在横屏与竖屏之间变化        //SCREEN_ORIENTATION_NOSENSOR: 忽略物理感应器——即显示方向与物理感应器无关,不管用户如何旋转设备显示方向都不会随着改变("unspecified"设置除外)        //SCREEN_ORIENTATION_UNSPECIFIED: 未指定,此为默认值,由Android系统自己选择适当的方向,选择策略视具体设备的配置情况而定,因此不同的设备会有不同的方向选择        //SCREEN_ORIENTATION_USER: 用户当前的首选方向        setContentView(R.layout.main);        back = (ImageView) findViewById(R.id.camera_back);        position = (ImageView) findViewById(R.id.camera_position);        surface = (SurfaceView) findViewById(R.id.camera_surface);        shutter = (ImageButton) findViewById(R.id.camera_shutter);        holder = surface.getHolder();//获得句柄        holder.addCallback(this);//添加回调        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//surfaceview不维护自己的缓冲区,等待屏幕渲染引擎将内容推送到用户面前        //设置监听        back.setOnClickListener(listener);        position.setOnClickListener(listener);        shutter.setOnClickListener(listener);    }    //响应点击事件    OnClickListener listener = new OnClickListener() {        @Override        public void onClick(View v) {            // TODO Auto-generated method stub            switch (v.getId()) {            case R.id.camera_back:                //返回                MyCameraActivity.this.finish();                break;            case R.id.camera_position:                //切换前后摄像头                int cameraCount = 0;                CameraInfo cameraInfo = new CameraInfo();                cameraCount = Camera.getNumberOfCameras();//得到摄像头的个数                for(int i = 0; i < cameraCount; i   ) {                    Camera.getCameraInfo(i, cameraInfo);//得到每一个摄像头的信息                    if(cameraPosition == 1) {                        //现在是后置,变更为前置                        if(cameraInfo.facing  == Camera.CameraInfo.CAMERA_FACING_FRONT) {//代表摄像头的方位,CAMERA_FACING_FRONT前置      CAMERA_FACING_BACK后置                              camera.stopPreview();//停掉原来摄像头的预览                            camera.release();//释放资源                            camera = null;//取消原来摄像头                            camera = Camera.open(i);//打开当前选中的摄像头                            try {                                camera.setPreviewDisplay(holder);//通过surfaceview显示取景画面                            } catch (IOException e) {                                // TODO Auto-generated catch block                                e.printStackTrace();                            }                            camera.startPreview();//开始预览                            cameraPosition = 0;                            break;                        }                    } else {                        //现在是前置, 变更为后置                        if(cameraInfo.facing  == Camera.CameraInfo.CAMERA_FACING_BACK) {//代表摄像头的方位,CAMERA_FACING_FRONT前置      CAMERA_FACING_BACK后置                              camera.stopPreview();//停掉原来摄像头的预览                            camera.release();//释放资源                            camera = null;//取消原来摄像头                            camera = Camera.open(i);//打开当前选中的摄像头                            try {                                camera.setPreviewDisplay(holder);//通过surfaceview显示取景画面                            } catch (IOException e) {                                // TODO Auto-generated catch block                                e.printStackTrace();                            }                            camera.startPreview();//开始预览                            cameraPosition = 1;                            break;                        }                    }                }                break;            case R.id.camera_shutter:                //快门                camera.autoFocus(new AutoFocusCallback() {//自动对焦                    @Override                    public void onAutoFocus(boolean success, Camera camera) {                        // TODO Auto-generated method stub                        if(success) {                            //设置参数,并拍照                            Parameters params = camera.getParameters();                            params.setPictureFormat(PixelFormat.JPEG);//图片格式                            params.setPreviewSize(800, 480);//图片大小                            camera.setParameters(params);//将参数设置到我的camera                            camera.takePicture(null, null, jpeg);//将拍摄到的照片给自定义的对象                        }                    }                });                break;            }        }    };    /*surfaceHolder他是系统提供的一个用来设置surfaceView的一个对象,而它通过surfaceView.getHolder()这个方法来获得。     Camera提供一个setPreviewDisplay(SurfaceHolder)的方法来连接*/    //SurfaceHolder.Callback,这是个holder用来显示surfaceView 数据的接口,他必须实现以下3个方法    @Override    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {        // TODO Auto-generated method stub    }    @Override    public void surfaceCreated(SurfaceHolder holder) {        // TODO Auto-generated method stub        //当surfaceview创建时开启相机        if(camera == null) {            camera = Camera.open();            try {                camera.setPreviewDisplay(holder);//通过surfaceview显示取景画面                camera.startPreview();//开始预览            } catch (IOException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }    }    @Override    public void surfaceDestroyed(SurfaceHolder holder) {        // TODO Auto-generated method stub        //当surfaceview关闭时,关闭预览并释放资源        camera.stopPreview();        camera.release();        camera = null;        holder = null;        surface = null;    }    //创建jpeg图片回调数据对象    PictureCallback jpeg = new PictureCallback() {        @Override        public void onPictureTaken(byte[] data, Camera camera) {            // TODO Auto-generated method stub            try {                Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);                //自定义文件保存路径  以拍摄时间区分命名                filepath = "/sdcard/Messages/MyPictures/"   new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())   ".jpg";                File file = new File(filepath);                BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);//将图片压缩的流里面                bos.flush();// 刷新此缓冲区的输出流                bos.close();// 关闭此输出流并释放与此流有关的所有系统资源                camera.stopPreview();//关闭预览 处理数据                camera.startPreview();//数据处理完后继续开始预览                bitmap.recycle();//回收bitmap空间            } catch (Exception e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }    };}




更多相关文章

  1. Android中显示html标签或者带图片
  2. android universalimageloader 几点改进
  3. 浅谈Android五大布局——LinearLayout、FrameLayout和AbsoulteLa
  4. Android(安卓)关于手指拖动onScroll、onFling...[geoway]
  5. Android之相机的使用
  6. Android中获取网络图片的三种方法
  7. SimpleCropView 裁剪图片
  8. 超炫的android 3d ui,目前正在内测中 期待
  9. [置顶] android利用zbar二维码扫描-(解决中文乱码及扫描区域定义

随机推荐

  1. 深入学习百度地图Android(安卓)SDK v4.0.
  2. 内存3
  3. Android(安卓)proguard.flags
  4. android 自学日记(六) ——SAX解析中换行问
  5. Firmware加载原理分析
  6. Android(安卓)修改HOSTS解决办法
  7. Android在诸如editText等组件设置输入法
  8. Android沉浸式状态栏变色
  9. Android(安卓)只开启一个Activity实例
  10. android微信纯图片分享和网页分享