在Android的开发过程中,我们可能会读取手机里面的照片或者通过相机拍摄获取照片,这是两种常用的获取图片的方式,在做项目过程中也会经常遇到,下面来介绍一下这两种获取方式..
1.从本地相册获取照片:
一般就是写出这个方法
- protected void getImageFromAlbum() {
- Intent intent = new Intent(Intent.ACTION_PICK);
- intent.setType("image/*");//相片类型
- startActivityForResult(intent, REQUEST_CODE_PICK_IMAGE);
- }
2.从照相机获取照片
一般就是写出这个方法
- protected void getImageFromCamera() {
- String state = Environment.getExternalStorageState();
- if (state.equals(Environment.MEDIA_MOUNTED)) {
- Intent getImageByCamera = new Intent("android.media.action.IMAGE_CAPTURE");
- startActivityForResult(getImageByCamera, REQUEST_CODE_CAPTURE_CAMEIA);
- }
- else {
- Toast.makeText(getApplicationContext(), "请确认已经插入SD卡", Toast.LENGTH_LONG).show();
- }
- }
写完这个方法后,一般我们还需要通过响应这个方法去获取图片
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (requestCode == REQUEST_CODE_PICK_IMAGE) {
- Uri uri = data.getData();
- //to do find the path of pic
- } else if (requestCode == REQUEST_CODE_CAPTURE_CAMEIA ) {
- Uri uri = data.getData();
- //to do find the path of pic
- } }
但是,有时候我们会发现用相机拍摄获取照片的时候,得到的 uri 是 null 的,这是因为android把拍摄的图片封装到bundle中传递回来,但是根据不同的机器获得相片的方式不太一样,可能有的相机能够通过
inten.getData()获取到uri
然后再根据uri获取数据的路径,在封装成bitmap,但有时候有的相机获取到的是null的,这时候我们该怎么办呢?
其实这时候我们就应该从bundle中获取数据,通过
(Bitmap) bundle.get("data")
获取到相机图片的bitmap数据。
为了能够同时适应上述两种情况,我们这时候就应该在获取图片时做判断了。我们可以在响应的时候做一个判断:
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (requestCode == REQUEST_CODE_PICK_IMAGE) {
- Uri uri = data.getData();
- //to do find the path of pic by uri
- } else if (requestCode == REQUEST_CODE_CAPTURE_CAMEIA ) {
- Uri uri = data.getData();
- if(uri == null){
- //use bundle to get data
- Bundle bundle = data.getExtras();
- if (bundle != null) {
- Bitmap photo = (Bitmap) bundle.get("data"); //get bitmap
- //spath :生成图片取个名字和路径包含类型
- saveImage(Bitmap photo, String spath);
- } else {
- Toast.makeText(getApplicationContext(), "err****", Toast.LENGTH_LONG).show();
- return;
- }
- }else{
- //to do find the path of pic by uri
- }
- }
- }
- public static void saveImage(Bitmap photo, String spath) {
- try {
- BufferedOutputStream bos = new BufferedOutputStream(
- new FileOutputStream(spath, false));
- photo.compress(Bitmap.CompressFormat.JPEG, 100, bos);
- bos.flush();
- bos.close();
- } catch (Exception e) {
- e.printStackTrace();
- return false;
- }
- return true;
- }
这样就能解决照相机取到的图片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;
}
}