android获取相册照片和获取拍照照片并做简单剪裁

在Android的开发过程中,我们可能会读取手机里面的照片或者通过相机拍摄获取照片,这是两种常用的获取图片的方式,在做项目过程中也会经常遇到,下面来介绍一下这两种获取方式..

1.从本地相册获取照片:

一般就是写出这个方法

[java]  view plain copy
  1. protected void getImageFromAlbum() {  
  2.        Intent intent = new Intent(Intent.ACTION_PICK);  
  3.        intent.setType("image/*");//相片类型  
  4.        startActivityForResult(intent, REQUEST_CODE_PICK_IMAGE);  
  5.    }  

2.从照相机获取照片

一般就是写出这个方法

[java]  view plain copy
  1. protected void getImageFromCamera() {  
  2.        String state = Environment.getExternalStorageState();  
  3.        if (state.equals(Environment.MEDIA_MOUNTED)) {  
  4.            Intent getImageByCamera = new Intent("android.media.action.IMAGE_CAPTURE");     
  5.            startActivityForResult(getImageByCamera, REQUEST_CODE_CAPTURE_CAMEIA);  
  6.        }  
  7.        else {  
  8.            Toast.makeText(getApplicationContext(), "请确认已经插入SD卡", Toast.LENGTH_LONG).show();  
  9.        }  
  10.    }  

写完这个方法后,一般我们还需要通过响应这个方法去获取图片

[java]  view plain copy
  1. @Override  
  2.     protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
  3.         if (requestCode == REQUEST_CODE_PICK_IMAGE) {             
  4.                 Uri uri = data.getData();  
  5.                 //to do find the path of pic  
  6.             
  7.         } else if (requestCode == REQUEST_CODE_CAPTURE_CAMEIA ) {             
  8.         Uri uri = data.getData();  
  9.                  //to do find the path of pic  
  10.  } }  

但是,有时候我们会发现用相机拍摄获取照片的时候,得到的 uri 是 null 的,这是因为android把拍摄的图片封装到bundle中传递回来,但是根据不同的机器获得相片的方式不太一样,可能有的相机能够通过  
inten.getData()获取到uri
然后再根据uri获取数据的路径,在封装成bitmap,但有时候有的相机获取到的是null的,这时候我们该怎么办呢?
其实这时候我们就应该从bundle中获取数据,通过
(Bitmap) bundle.get("data")
获取到相机图片的bitmap数据。
为了能够同时适应上述两种情况,我们这时候就应该在获取图片时做判断了。我们可以在响应的时候做一个判断:

[java]  view plain copy
  1. @Override  
  2.    protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
  3.        if (requestCode == REQUEST_CODE_PICK_IMAGE) {             
  4.                Uri uri = data.getData();  
  5.                //to do find the path of pic by uri  
  6.            
  7.        } else if (requestCode == REQUEST_CODE_CAPTURE_CAMEIA ) {             
  8.        Uri uri = data.getData();  
  9.        if(uri == null){  
  10.            //use bundle to get data  
  11.            Bundle bundle = data.getExtras();    
  12.                if (bundle != null) {                 
  13.                Bitmap  photo = (Bitmap) bundle.get("data"); //get bitmap  
  14.                //spath :生成图片取个名字和路径包含类型                              
  15.                saveImage(Bitmap photo, String spath);  
  16.                } else {           
  17.                    Toast.makeText(getApplicationContext(), "err****", Toast.LENGTH_LONG).show();           
  18.                 return;        
  19.                 }    
  20.        }else{  
  21.                 //to do find the path of pic by uri  
  22.        }   
  23.    }  
  24. }  
后面的过程就需要通过bitmap转化成相应的图片文件了。不过得到最终 的图片是被压缩了的

[java]  view plain copy
  1. public static void saveImage(Bitmap photo, String spath) {  
  2.         try {  
  3.             BufferedOutputStream bos = new BufferedOutputStream(  
  4.                     new FileOutputStream(spath, false));  
  5.             photo.compress(Bitmap.CompressFormat.JPEG, 100, bos);  
  6.             bos.flush();  
  7.             bos.close();  
  8.         } catch (Exception e) {  
  9.             e.printStackTrace();  
  10.             return false;  
  11.         }  
  12.         return true;  
  13.     }  

这样就能解决照相机取到的图片uri为空的状态了。但是在获取到uri为null情况下,如果想得到没有被压缩过的照片,也就是说得到的是直接从相机拍摄到的照片怎么做呢?

其实方式很简单,在Intent getImageByCamera = new Intent("android.media.action.IMAGE_CAPTURE");之后我们直接讲文件先保存到指定的路径filepath,然后直接在onActivityResult(int requestCode, int resultCode, Intent data)中把filepath传递过去就行了。

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

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.拍照时,将拍得的照片先保存在本地,通过修改之前的代码如下:

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

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

@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.打开相册选取图片

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

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

@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;
      }
    }
  }
package com.picture.test;


import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;

import com.example.communication.R;

public class PictureActivity extends Activity {
    private ImageView mImageView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.picture);
        mImageView = (ImageView) findViewById(R.id.boundPicture);
        Bitmap mBitmap = ((BitmapDrawable)getResources().getDrawable(R.drawable.hospital_img_nomal)).getBitmap();
        mImageView.setImageDrawable(new BitmapDrawable(cutBitmap(mBitmap, 4)));
        mImageView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
//                Intent mIntent = new Intent(PictureActivity.this, TestRobotActivity.class);
//                startActivity(mIntent);
                showPictureDialog();
            }
        });
        getFileName("D:/SVN manager/TortoiseSVN/bin/autolist.txt"+"\n"+"joker");
    }
    private String capturePath;
    public void showPictureDialog() {
        new AlertDialog.Builder(this).setTitle("choose").setItems(getResources().getStringArray(R.array.picturechoose),
                new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        switch (which) {
                            case 0:
                                Intent mGalleryIntent = new Intent();
                                mGalleryIntent.setType("image/*");
                                mGalleryIntent.setAction(Intent.ACTION_GET_CONTENT);
                                startActivityForResult(mGalleryIntent, 0);
                                break;
                            case 1:
                                Intent mTakePhoneIntent = new Intent();
                                String root = "";
                                if(isHaveSdCard()) {
                                    root = Environment.getExternalStorageDirectory() + "/";
                                }
                                capturePath = root + System.currentTimeMillis() +".jpg";
                                File mFile = new File(root);
                                if(!mFile.exists()) {
                                    mFile.mkdirs();
                                }
                                //获取相机拍摄的原图片需要添加第一句话
                                mTakePhoneIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(capturePath)));  
                                mTakePhoneIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);  
                                //
                                mTakePhoneIntent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
                                startActivityForResult(mTakePhoneIntent, 1);
                                break;
                            default:
                                break;
                        }
                    }
                }).show();
    }
    private Intent mCamera;
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(resultCode == RESULT_OK) {
            switch (requestCode) {
                case 0:
                    if(data == null) {
                        return;
                    }
                    Uri mUri = data.getData();
                    startCutting(mUri);
                    break;
                case 1:
                    
                  //拍照——直接获取原图片并显示
                    Bitmap mBitmap = BitmapFactory.decodeFile(capturePath);
                    Bitmap newBitmap = cutBitmap(mBitmap,3);
                    mBitmap.recycle();
                    mImageView.setImageDrawable(new BitmapDrawable(mBitmap));
                   //
                   //拍照——获取自动压缩后的图片
//                    if (data.getData() != null) {
//                        startCutting(data.getData());
//                        mCamera = data;
//                    }
//                    else {
//                        getImageToView(data);
//                    }
                    break;
                case 2:
                    if(data == null) {
                        return;
                    }
                    getImageToView(data);
                    //删除所拍的照片
                    if(mCamera != null) {
                        doDeleteDCIMPhoto(mCamera);
                        mCamera = null;
                    }
                    break;
                default:
                    break;
            }
        }
    }
    
    protected void startCutting(Uri uri) {
        Intent mIntent = new Intent("com.android.camera.action.CROP");
        mIntent.setDataAndType(uri, "image/*");
        mIntent.putExtra("crop", "true");
        mIntent.putExtra("aspectX", 1);
        mIntent.putExtra("aspectY", 1);
        mIntent.putExtra("outputX", 300);
        mIntent.putExtra("outputY", 300);
        mIntent.putExtra("return-data", true);
        startActivityForResult(mIntent, 2);
    }
    
    protected void getImageToView(Intent data) {
        Bundle mBundle = data.getExtras();
        if(mBundle != null) {
            Bitmap mBitmap = mBundle.getParcelable("data");
            String root = "";
            if(isHaveSdCard()) {
                root = Environment.getExternalStorageDirectory() + "/";
            }
            String path = root + "images/";
            String picName = "head.jpg";
            savePhoto2File(root, picName, mBitmap, 80);
            Drawable mDrawable = new BitmapDrawable(getRoundedCornerBitmap(mBitmap, 2));
            mImageView.setImageDrawable(mDrawable);
        }
    }
    
    protected boolean isHaveSdCard() {
        boolean isHave = false;
        String state = Environment.getExternalStorageState();
        if (state != null && Environment.MEDIA_MOUNTED.equals(state)
                && !Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
            isHave = true;
        }
        return isHave;
    }
    /**
     * 删除系统的照片
     * 
     * @param data
     */
    public void doDeleteDCIMPhoto(Intent data) {
        if (data != null) {
            // 获取系统拍照图片路径
            Uri uri_DCIM = null;
            if (data.getData() != null) {
                uri_DCIM = data.getData();
            }
            else {
                uri_DCIM = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
            }
            String DCIMPath = "";
            Cursor cr = this.getContentResolver().query(uri_DCIM, new String[]{MediaStore.Images.Media.DATA}, null,
                    null, MediaStore.Images.Media.DATE_MODIFIED + " desc");
            if (cr != null) {
                if (cr.moveToNext()) {
                    DCIMPath = cr.getString(cr.getColumnIndex(MediaStore.Images.Media.DATA));
                }
                cr.close();
                cr = null;
                // 删除系统拍照图片
                if (!TextUtils.isEmpty(DCIMPath)) {
                    boolean bool_delete = new File(DCIMPath).delete();
                    this.getContentResolver().delete(uri_DCIM, "_data=?", new String[]{DCIMPath});
                }
            }

        }

    }

    public static int savePhoto2File(String path, String picName, Bitmap bitmap, int compressvalue) {
        if(bitmap == null) {
            return -1;
        }
        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {  
            final String saveDir = path;  
            final File dir = new File(saveDir);  
            if (!dir.exists()) {  
                dir.mkdirs();
            }  
            final File file = new File(saveDir, picName);  
//          file.delete();  
            
            FileOutputStream os = null;
            try {  
                os = new FileOutputStream(file);  
                bitmap.compress(Bitmap.CompressFormat.JPEG, compressvalue, os);// 把数据写入文件   
            } 
            catch (FileNotFoundException e) {  
                e.printStackTrace();
                return -2;
            } 
            catch (Exception e) {
                e.printStackTrace();
                return -3;
            }
            finally {  
                try {  
                    if(os != null) {
                        os.flush();  
                        os.close();
                        os = null;
                    }
                } 
                catch (IOException e) {  
                    e.printStackTrace();  
                }  
            }  

        } 
        else {  
            return -4;
        } 
        
        return 1;
    }
    
    protected String getFileName(String filePath) {
        Log.i("filePath = ", filePath);
        int index = filePath.lastIndexOf('/');
        String name = null;
        if(index > -1) {
            name= filePath.substring(index+1);
            name = name.replaceAll("\\?", "_");
            Log.i("name = ", name);
        }
        return name;
    }
    
    /**
     * 裁剪图片
     * 
     * @param sourceBitmap
     * @param WHRadio
     *            宽 高 比例
     * @return
     */
    public static Bitmap cutBitmap(Bitmap sourceBitmap, float WHRadio) {
        if (sourceBitmap == null) {
            return null;
        }
        int targetWidth = sourceBitmap.getWidth();
        int sourceHeight = sourceBitmap.getHeight();
        int targetHeight = sourceHeight;

        if (targetWidth * 1.0f / targetHeight < WHRadio) {
            targetHeight = (int) (targetWidth/WHRadio);
        }
        else {
            return sourceBitmap;
        }
        Bitmap targetBitmap = null;
        try {
            targetBitmap = Bitmap.createBitmap(targetWidth, targetHeight, Bitmap.Config.ARGB_8888);
        }
        catch (OutOfMemoryError oom) {
            oom.printStackTrace();
            System.gc();
            return null;
        }
        Canvas canvas = new Canvas(targetBitmap);
        int sourceTop = (sourceHeight - targetHeight) / 2;
        canvas.drawBitmap(sourceBitmap, new Rect(0, sourceTop, sourceBitmap.getWidth(), sourceTop + targetHeight),
                new Rect(0, 0, targetWidth, targetHeight), null);
        //
        sourceBitmap.recycle();
        sourceBitmap = null;

        return targetBitmap;
    }

   public static Bitmap compressImage(Bitmap image) {
       ByteArrayOutputStream mArrayOutputStream = new ByteArrayOutputStream();
       image.compress(CompressFormat.PNG, 50, mArrayOutputStream);
       
       ByteArrayInputStream mByteArrayInputStream = new ByteArrayInputStream(mArrayOutputStream.toByteArray());
       Bitmap mBitmap = BitmapFactory.decodeStream(mByteArrayInputStream);
       return mBitmap;
   }
    
    public static Bitmap getRoundedCornerBitmap(Bitmap bitmap) {
        return getRoundedCornerBitmap(bitmap, 2);
    }
    /**
     * 剪切图片成圆
     * @param bitmap
     * @param ratio
     * @return
     */
    public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, int ratio) {
        if (bitmap == null || bitmap.isRecycled()) {
            return null;
        }
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        if (width > height) {
            width = height;
        }
        else {
            height = width;
        }
        Bitmap output = null;
        try {
            output = Bitmap.createBitmap(width, height, Config.ARGB_4444);
        }
        catch (OutOfMemoryError e) {
            e.printStackTrace();
            bitmap.recycle();
            bitmap = null;
            return null;
        }
        final Canvas canvas = new Canvas(output);

        final int color = Color.RED;
        final Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, width, height);
        final RectF rectF = new RectF(rect);
        // final float roundPx = pixels;
        if (ratio == 0) {
            ratio = 2;
        }
        final float roundPx = height*10;

        paint.setAntiAlias(true);
        paint.setStrokeWidth(5.0f);
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(color);
        canvas.drawRoundRect(rectF, roundPx, roundPx, paint);

        paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
        canvas.drawBitmap(bitmap, rect, rect, paint);
        canvas.drawLine(0, 0, width, height, paint);
        //
        if (bitmap != null && !bitmap.isRecycled()) {
            bitmap = null;
        }
        return output;
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值