调用系统相机/相册获取图片,并裁剪图片,在百度上找一下能搜到一大堆文章,然而拿过来在真机上跑一下大部分都有问题,根本达不到想要的效果。
为什么会拿不到想要的图片呢,最主要的原因是因为图片太大,而获取的图片数据是放在Intent中的。而现在手机的像素普遍都是800W+,一张普通的尺寸为3200*2400px的照片要消耗30MB的内存空间,而一个Intent能传递的数据怎么可能支持这么大的空间,我测试过一些手机能有1MB已经很开心了。
那么图片不放在Intent中,放在哪里呢。好吧,重要的事情我要说三遍:
“截大图用Uri,截小图用Bitmap”“截大图用Uri,截小图用Bitmap”
“截大图用Uri,截小图用Bitmap”
对待大图片时应该用Uri返回数据,小图片才用Bitmap返回数据,不过现在基本都是大图片,还是放弃Bitmap的方式吧。
裁剪图片的关键代码:
intent.putExtra("return-data", false); intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
实现代码如下:
private static final String IMAGE_FILE_LOCATION = "file://" + new File(Environment.getExternalStorageDirectory(), "temp.jpg").getAbsolutePath();//temp file private Uri imageUri = Uri.parse(IMAGE_FILE_LOCATION);//The Uri to store the big bitmap @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { //Log.i(TAG, "onActivityResult() requestCode = " + requestCode + " resultCode = " + resultCode); if (resultCode == RESULT_OK) { switch (requestCode) { case Constant.UPLOAD_LOCAL_IMAGE: // 获取本地相片 // 获取本地相片的地址 getImagpath(data); startPhotoZoom(data.getData()); break; case Constant.UPLOAD_CAMERA_IMAGE: // 拍摄照片 //Log.i(TAG, "onActivityResult() case Constant.UPLOAD_CAMERA_IMAGE "); // 获取原图 getYuanTu(); break; case Constant.CAI_JIAN_IMAGE: Log.i(TAG, "onActivityResult() requestCode = case Constant.CAI_JIAN_IMAGE (imageUri != null) = " + (imageUri != null)); if(imageUri != null){ Bitmap bitmap = decodeUriAsBitmap(imageUri);//decode bitmap Log.i(TAG, "onActivityResult() CAI_JIAN_IMAGE = bitmap " + bitmap); if (bitmap != null) { mImageColorTip.setImageBitmap(bitmap); } } break; } } if (resultCode == Constant.ACTIVIT_FINISH) { //Log.i(TAG, "onActivityResult() (resultCode == Constant.ACTIVIT_FINISH)"); finish(); } //super.onActivityResult(requestCode, resultCode, data); } private Bitmap decodeUriAsBitmap(Uri uri){ Bitmap bitmap = null; try { bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri)); } catch (FileNotFoundException e) { Log.w(TAG, "decodeUriAsBitmap()", e); return null; } return bitmap; } private void takePicture() { String sDCard = SDCardPath.checkSDCard(); //Log.i(TAG, "takePicture() (sDCard == null) = " + (sDCard == null)); if (sDCard == null) { showToast(R.string.text_sd_card_invailable); } else { try { String filePath = SDCardPath.getFilePath(sDCard); String imagePath = SDCardPath.getImagePath(filePath); // 下面这句指定调用相机拍照后的照片存储的路径 File dir = new File(filePath + "/"); if (!dir.exists()) { dir.mkdirs(); } File tmpFile = new File(dir, imagePath); if (!tmpFile.exists()) { tmpFile.createNewFile(); } Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(tmpFile)); TakePhotoColorActivity.sImagePath = tmpFile.getAbsolutePath(); startActivityForResult(intent,Constant.UPLOAD_CAMERA_IMAGE); } catch (IOException e) { Log.e(TAG, "openAlbum() IOException", e); } } } private void openAlbum() { //Log.i(TAG, "openAlbum()"); Intent intent = new Intent(Intent.ACTION_PICK, null); intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*"); startActivityForResult(intent,Constant.UPLOAD_LOCAL_IMAGE); } /** * 获取原图的方法 */ private void getYuanTu() { //Log.i(TAG, "getYuanTu() PictureColorActivity.sImagePath = " + PictureColorActivity.sImagePath); File f = new File(TakePhotoColorActivity.sImagePath); // Log.i(TAG, "getYuanTu() filePath = " + (f == null ? "iOnesNull" : f.getAbsolutePath())); try { String imgURL = null; try { imgURL = android.provider.MediaStore.Images.Media.insertImage(getContentResolver(), f.getAbsolutePath(), null, null); } catch (Exception e) { Log.e(TAG, "getYuanTu() imgURL", e); } // Log.i(TAG, "getYuanTu() imgURL = " + imgURL); Uri u = null; if (imgURL != null) { u = Uri.parse(imgURL); } else { u = Uri.fromFile(f); } // Log.i(TAG, "getYuanTu() uri = " + (u == null ? "iOnesNull" : u.toString())); startPhotoZoom(u); } catch (Exception e) { Log.e(TAG, "getYuanTu()", e); } } /** * 获取本地图片的路径 * * @param data */ private void getImagpath(Intent data) { //Log.i(TAG, "getImagpath() PictureColorActivity.sImagePath = " + PictureColorActivity.sImagePath); Uri originalUri = data.getData(); // 获得图片的uri String[] proj = { MediaStore.Images.Media.DATA }; // 好像是android多媒体数据库的封装接口,具体的看Android文档 // Cursor cursor = managedQuery(originalUri, proj, null, null, null); Cursor cursor = getContentResolver().query(originalUri, proj, null, null, null); // 按我个人理解 这个是获得用户选择的图片的索引值 int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); // 将光标移至开头 ,这个很重要,不小心很容易引起越界 cursor.moveToFirst(); // 最后根据索引值获取图片路径 String path = cursor.getString(column_index); TakePhotoColorActivity.sImagePath = path; } /** * 裁剪图片方法实现 * * @param uri */ public void startPhotoZoom(Uri uri) { //Log.i(TAG, "startPhotoZoom() PictureColorActivity.sImagePath = " + PictureColorActivity.sImagePath); Intent intent = new Intent("com.android.camera.action.CROP"); intent.setDataAndType(uri, "image/*"); // 下面这个crop=true是设置在开启的Intent中设置显示的VIEW可裁剪 intent.putExtra("crop", "true"); // aspectX aspectY 是宽高的比例 intent.putExtra("aspectX", 1); intent.putExtra("aspectY", 1); intent.putExtra("scale", true); // outputX outputY 是裁剪图片宽高 // TODO 详情参考:http://my.oschina.net/ryanhoo/blog/86842 intent.putExtra("outputX", 500); intent.putExtra("outputY", 500); intent.putExtra("noFaceDetection", true); intent.putExtra("return-data", false); Log.i(TAG, "startPhotoZoom() (imageUri != null) = " + (imageUri != null)); intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString()); startActivityForResult(intent, Constant.CAI_JIAN_IMAGE); } /** 大图图片的路径 */ private static String sImagePath = ""; public interface Constant { /** * 获取本地图片 */ public static final int UPLOAD_LOCAL_IMAGE = 0x0001; /** * 获取相机图片 */ public static final int UPLOAD_CAMERA_IMAGE = 0x0002; public static final String SD_CARD_ROOT = "sdcard"; /** * 裁剪图片 */ public static final int CAI_JIAN_IMAGE=0x0003; /** * 回调结束当前界面 */ public static final int ACTIVIT_FINISH = 0x0004; /**相机裁剪后的照片*/ public static final int IMAGE_CODE_PATH = 0x0005; }
如果对你有帮助,不要谢我。大神在这里:http://my.oschina.net/ryanhoo/blog/86842