zoukankan      html  css  js  c++  java
  • Android在有存储卡和无存储卡情况下拍照后固定尺寸和压缩大小

      我最近工作挺忙,距离上一次写博客转眼已经过了一个多月,每次学到和用到点新东西,其实都有分享的欲望,但奈何文笔太差,而一篇文章包括构思,排版,修改发布的时间最少要花费2个小时(这其中还不包括写完后未保存,突然关掉浏览器的惨剧…),但是今天不知怎么的突然头脑发热,决定把睡觉的2个小时用来写篇博客(请原谅我放荡不羁爱睡觉zZ...)。

      最近做的一个项目是为某企业做得一个门店拜访APP。需要用到拍照上传的功能。刚开始确定需求的时候,客户只要求实现拍照上传的功能,这个简单,直接调用系统的拍照不就行了,代码如下:

    public void btnClick(View view){
        if(view.getId()==R.id.kpi_btn_takePhoto){
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 
            startActivityForResult(intent, 0); 
        }
    }
    protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
        if (requestCode== 0&&resultCode==RESULT_OK) {
            Bundle extras = data.getExtras(); 
            Bitmap b = (Bitmap) extras.get("data"); 
            //TO DO 保存照片到sdcard和上传图片代码省略…
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

      上面的btnClick()方法是点击拍照按钮时触发的方法,而且基本满足了客户的需求,拿给客户一看,客户一看,恩,看着我一笑,顿觉满园菊花香。

      但变更需求注定是程序员的最大敌人,果然,第二天,客户就来电话了,说用你们APP拍的照片模糊,尺寸不够(别邪恶哦(⊙o⊙)…)…没办法,那就改呗,但上面的方法是不能再用了,因为上面的方法只能获取一个缩略图。要想通过拍照获取原图并进行压缩,我们就要用到下面这个方法了,请看:

                                 
    public void btnClick(View view){
      if(view.getId()==R.id.kpi_btn_takePhoto){
        Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");  
        mPhotoPath= Environment.getExternalStorageDirectory().getAbsolutePath()+”t.jpg”;  
         mPhotoFile = new File(mPhotoPath);  
        if (!mPhotoFile.exists()) {  
          mPhotoFile.createNewFile();  
        }  
        intent.putExtra(MediaStore.EXTRA_OUTPUT,     Uri.fromFile(mPhotoFile));  
        startActivityForResult(intent,CAMERA_RESULT);
      }
    }
    protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
      if (requestCode== 0&&resultCode==RESULT_OK) {
        Bitmap bitmap = getSmallBitmap (mPhotoPath);
        //TO DO 保存照片到sdcard和上传图片代码省略…
      }
      super.onActivityResult(requestCode, resultCode, data);
    }
    public Bitmap getSmallBitmap(String filePath) {
      final BitmapFactory.Options options = new BitmapFactory.Options();
      options.inJustDecodeBounds = true;
      BitmapFactory.decodeFile(filePath, options);
      options.inSampleSize =calculateInSampleSize(options, 600, 800);
      options.inJustDecodeBounds = false;
      return BitmapFactory.decodeFile(filePath, options);
    }

      其中,getSmallBitmap()方法主要是对原图进行了等比压缩,经过这样处理后,图像几乎没怎么失真,而且只有200多K,发给客户一看,客户又高兴了(我绝对不会说客户都有着一颗逗比的心…我也绝对不会去捡肥皂的,哼!)。

      虽然知道需求可能还会变,但这次等待的时间有点久了,这次是在项目快上线的时候问题来了,你说,很多程序员加班加点容易吗(满满的负能量)。。。

      回到几天前,因为上线前,客户那边也是要对APP进行测试几天的,于是公司就采购了几台不同型号的手机,但是没装存储卡就发过去了,但客户测试拍照功能的时候问题就来了,其实这也只能怪我们这边,机子自己都没测,就发给客户那边了。因为前面我们拍照设置的保存路径是放在sdcard卡里,没插sdcard,这样一来,拍照功能就不能用了,我们开始的想法是叫客户那边自己插个sdcard,但客户却一定要说这是一个bug(呵呵,我会说微信,毁图秀秀没sdcard都拍不了照吗?)。。。无奈,客户是干爹,不爽归不爽,为了钱还是得服务不是?既然手机没用外存储卡,那么我们应用程序只能通过去访问data/data/package name/下的目录啦,想到做到,那就开始动手呗。代码如下:

    public void btnClick(View view) {
        Intent intent = new ntent(MediaStore.ACTION_IMAGE_CAPTURE);
        String state = Environment.getExternalStorageState();
        if (state.equals(Environment.MEDIA_MOUNTED)) {
            //有sdcard
        mPhotoPath= Environment.getExternalStorageDirectory().getAbsolutePath()+”t.jpg”;    
            File file=new File(mPhotoPath);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new file));
        }else{
            //没有sdcard,只能获取缩略图
        }
        tartActivityForResult(intent, 0);
    }
    protected void onActivityResult(int requestCode, int resultCode, Intent data){ 
         if (requestCode== 0&&resultCode==RESULT_OK) {
            Bitmap bitmap = getSmallBitmap (mPhotoPath);
            //TO DO 保存照片到sdcard和上传图片代码省略…
        }
        super.onActivityResult(requestCode, resultCode, data);
    }
    public Bitmap getSmallBitmap(String filePath) {
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(filePath, options);
        options.inSampleSize = calculateInSampleSize(options, 600, 800);
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeFile(filePath, options);
    }     

      弄完一测试,效果不错,有挂载存储卡就存储在存储卡上,没挂载存储卡就存应用中。于是,马上就将新版本发布到服务器上让客户自己下载去了,毕竟上线在即啊。但,毕竟未完待续…

      第二天,客户电话又来了,原来,我们前面拍照的图片是通过等比压缩来实现图片压缩的,因此不同的手机,压缩后照片像素就会不同,有600*800的,有1280*800,等等。但客户想要拍照后获取的是固定像素的照片,并且要求大小是150-200K,好吧,拿了工资还是得干活不是,百度,google一番,发现Bitmap 有个createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter)方法,可以获得一个固定像素大小的bitmap,bingo!第一个要求有解决方案了。至于压缩到固定范围,因为不同的手机,拍的照片所占大小肯定是不同的,但是他们都是可以不断压缩的呀,那我们写一个循环来不断压缩,直压缩到小于200K不就行了?ok,有了解决方案就好办事,10分钟后,结果如下:

    public void btnClick(View view) {
        Intent intent = new ntent(MediaStore.ACTION_IMAGE_CAPTURE);
        String state = Environment.getExternalStorageState();
        if (state.equals(Environment.MEDIA_MOUNTED)) {
        //有sdcard
        mPhotoPath= Environment.getExternalStorageDirectory().getAbsolutePath()+”t.jpg”;    
            File file=new File(mPhotoPath);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new file));
        }else{
            //没有sdcard,只能获取缩略图
        }
        tartActivityForResult(intent, 0);
    }
    protected void onActivityResult(int requestCode, int resultCode, Intent data){ 
        if (requestCode== 0&&resultCode==RESULT_OK) {
        Bitmap bitmap =Bitmap.createScaledBitmap(BitmapFactory.decodeFile(filePath), 600, 800, true);
        int quality=98;
        bitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos);
        while (baos.toByteArray().length / 1024 > 200) {
            quality-= 1;// 每次都减少1
            baos.reset();// 重置baos即清空baos
            bitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos);// 这里压缩options%,把压缩后的数据存放到baos中                }
        //TO DO 保存照片到sdcard和上传图片代码省略…
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

      ok,至此,拍照上传模块总算有了一个较为完美的解决方案,当然不可能是十全十美的,还是欢迎大家善意指正。

  • 相关阅读:
    TVB西游记-观音的眼泪化作金河送唐僧回长安
    天下没有免费的午餐是什么意思
    什么样的经历、体验或者行为等能彻底的改变一个人
    看人先看什么
    python字符串中查找指定子字符串
    字符串的分隔及连接
    流媒体服务器音视频直播平台的开发为什么需要CDN?
    微信公众号小程序如何做流媒体视频直播?
    搭建专属于自己的视频流媒体直播/点播平台都需要注意哪些事项?
    音视频流媒体服务器的虚拟直播推流失败断流无法播放如何解决?
  • 原文地址:https://www.cnblogs.com/xiaoyang2009/p/3644289.html
Copyright © 2011-2022 走看看