• Android相机、相册获取图片显示并保存到SD卡


    Android相机、相册获取图片显示并保存到SD卡 

    [复制链接]
     
    跳转到指定楼层
    楼主
     
     发表于 2013-3-13 19:51:43 | 只看该作者 |只看大图 回帖奖励
    本帖最后由 happy小妖同学 于 2013-4-19 18:02 编辑

    如题,这个需求本不是一个很复杂的过程,但是却存在一些隐患,我也是最近在项目中碰到这个问题,将Android通过相机或相册获取图片并最终显示在界面上做了一个小研究,现将一些结果和附上的一个Demo叙述如下:

    做过类似需求的同学都知道,在Activity中通过如下代码可以启动相机,然后在重写的onActivityResult方法中可以获取到返回的照片数据:


    [java] view plaincopy


    • Intent openCameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);  
    • startActivityForResult(openCameraIntent, TAKE_PICTURE);  


    问题来了,不知大家是否有发现,在onActivityResult方法里通过Intent的getData方法获取的数据转换成bitmap并显示在界面上,有时候会有取不到数据,或者显示的bitmap会非常小,如果将bitmap保存到sd卡后会发现,图片的分辨率很低,并且图片大小也是经过压缩的,不管将相机的像素设置多高,最后通过这种方式返回的bitmap总是经过压缩了的。如果想获得理想的照片大小和分辨率改如何处理呢?以下是我的处理方法,虽然不是最好,但是帮我解决了这个需求。我先来简述一下为什么返回的图片是经过了压缩的。

    大家都知道,现在手机像素少则500W或800W,多则4KW(某亚),就拿常见的800W像素的相机拍出来的照片来说,分辨率大概在3200*2400左右,我的测试机型是LG optimus 2x,2.3.7的系统,用800W像素拍出来大概就是这个分辨率,照片大小在2M左右。试想一下,在Android系统中bitmap占用4个字节,3200*2400*4=?,结果大家自己算算,如果为了一张图片,耗用这么大的内存,肯定是不合理的,并且,官方文档中有说明,Android系统分配给每个应用的最大内存是16M,所以,系统为了防止应用内存占用过大,对于在应用内通过相机拍摄的图片最终返回来的结果进行了压缩,压缩后的图片变得很小,通过之前说的getData的方式只能满足比如显示个头像这样的需求,如果要显示大图,就会出现模糊的情况。那如何获取清晰的大图呢?我的解决思路如下:

    1.拍照时,将拍得的照片先保存在本地,通过修改之前的代码如下:


    [java] view plaincopy


    • Uri imageUri = Uri.fromFile(new File(Environment.getExternalStorageDirectory(),"image.jpg"));  
    • //指定照片保存路径(SD卡),image.jpg为一个临时文件,每次拍照后这个图片都会被替换  
    • openCameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);  


    2.在onActivityResult方法中再将图片取出,并经过缩小处理再显示在界面上或上传给服务器(压缩比例自定义)

    [java] view plaincopy


    • @Override  
    •     protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
    •         super.onActivityResult(requestCode, resultCode, data);  
    •         if (resultCode == RESULT_OK) {  
    •             switch (requestCode) {  
    •             case TAKE_PICTURE:  
    •                 //将保存在本地的图片取出并缩小后显示在界面上  
    •                 Bitmap bitmap = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory()+"/image.jpg");  
    •                 Bitmap newBitmap = ImageTools.zoomBitmap(bitmap, bitmap.getWidth() / SCALE, bitmap.getHeight() / SCALE);  
    •                 //由于Bitmap内存占用较大,这里需要回收内存,否则会报out of memory异常  
    •                 bitmap.recycle();  
    •                   
    •                 //将处理过的图片显示在界面上,并保存到本地  
    •                 iv_image.setImageBitmap(newBitmap);  
    •                 ImageTools.savePhotoToSDCard(newBitmap, Environment.getExternalStorageDirectory().getAbsolutePath(), String.valueOf(System.currentTimeMillis()));  
    •                 break;  
    •             default:  
    •                 break;  
    •             }  
    •         }  
    •     }  


    由于Android给bitmap分配的内存最大不超过8M,所以对使用完的较大的Bitmap要释放内存,调用其recycle()方法即可。然后将缩小(缩小方法在Demo源码中有)后的bitmap显示在界面上或保存到SD卡,至于之前保存的原图,可以删掉,也可以放在那,下次拍照时,这张原图就会被下一张照片覆盖,所以SD卡上使用只有一张临时图片,占用也不是很大。

    以上讲的是拍照获取图片,如果是从相册中获取图片又如何处理呢,我的方法如下:

    1.打开相册选取图片


    [java] view plaincopy


    • Intent openAlbumIntent = new Intent(Intent.ACTION_GET_CONTENT);  
    •                     openAlbumIntent.setType("image/*");  
    •                     startActivityForResult(openAlbumIntent, CHOOSE_PICTURE);  


    2.在onActivity方法中处理获取到的图片,思路和之前类似

    [java] view plaincopy


    • @Override  
    •     protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
    •         super.onActivityResult(requestCode, resultCode, data);  
    •         if (resultCode == RESULT_OK) {  
    •             switch (requestCode) {  
    •             case CHOOSE_PICTURE:  
    •                 ContentResolver resolver = getContentResolver();  
    •                 //照片的原始资源地址  
    •                 Uri originalUri = data.getData();   
    •                 try {  
    •                     //使用ContentProvider通过URI获取原始图片  
    •                     Bitmap photo = MediaStore.Images.Media.getBitmap(resolver, originalUri);  
    •                     if (photo != null) {  
    •                         //为防止原始图片过大导致内存溢出,这里先缩小原图显示,然后释放原始Bitmap占用的内存  
    •                         Bitmap smallBitmap = ImageTools.zoomBitmap(photo, photo.getWidth() / SCALE, photo.getHeight() / SCALE);  
    •                         //释放原始图片占用的内存,防止out of memory异常发生  
    •                         photo.recycle();  
    •                           
    •                         iv_image.setImageBitmap(smallBitmap);  
    •                     }  
    •                 } catch (FileNotFoundException e) {  
    •                     e.printStackTrace();  
    •                 } catch (IOException e) {  
    •                     e.printStackTrace();  
    •                 }   
    •                 break;  
    •               
    •             default:  
    •                 break;  
    •             }  
    •         }  
    •     }  


    补充,这个附件是所有要用到的我都封装好了。直接拷到项目里面就OK了。Activity就用网上随便的一个都行,就没有单独写个demo出来了。



    <ignore_js_op style="-ms-word-wrap: break-word;">
    该贴已经同步到 happy小妖同学的微博
    <ignore_js_op style="-ms-word-wrap: break-word;">

    myzxing.zip

     

    314.17 KB, 下载次数: 150, 下载积分: 下载豆 -2

    路漫漫其修远兮 吾将上下而求索
  • 相关阅读:
    EF
    采用什么架构,才能够承受大访问量
    13个MVC的扩展
    c#与.NET的区别
    整合Spring.net到asp.net网站开发中初探
    C#多线程编程简述
    ASP.NET页面传值的几种方式
    正则RegEXp
    C#中Cache用法
    c#程序将excel文件转换成xml文件
  • 原文地址:https://www.cnblogs.com/hudabing/p/3274062.html
Copyright © 2020-2023  润新知