在onActivityResult方法里通过Intent的getData方法获取的数据转换成bitmap并显示在界面上,有时候会有取不到数据,或者显示的bitmap会非常小,如果将bitmap保存到sd卡后会发现,图片的分辨率很低,并且图片大小也是经过压缩的,不管将相机的像素设置多高,最后通过这种方式返回的bitmap总是经过压缩了的。如果想获得理想的照片大小和分辨率改如何处理呢?我先来简述一下为什么返回的图片是经过了压缩的。
现在像机性能高了照片大小在好几M。试想一下,如果为了一张图片,耗用这么大的内存,肯定是不合理的,并且,官方文档中有说明,Android系统分配给每个应用的最大内存是16M,所以,系统为了防止应用内存占用过大,对于在应用内通过相机拍摄的图片最终返回来的结果进行了压缩,压缩后的图片变得很小,通过之前说的getData的方式只能满足比如显示个头像这样的需求,如果要显示大图,就会出现模糊的情况。那如何获取清晰的大图呢?我的解决思路如下:拍照时,将拍得的照片先保存在本地
先声明权限:
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
布局文件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.getpicture_fromlocaloropencamera.MainActivity" >
<Button
android:id="@+id/openLocalPicture_bt"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="打开本地相册" />
<Button
android:id="@+id/openCamera_bt"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="打开相机" />
<ImageView
android:id="@+id/userhead_iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@drawable/ic_launcher"
android:text="@string/hello_world" />
</LinearLayout>
创建工具类:
ImageTools
package com.example.getpicture_fromlocaloropencamera;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
public class ImageTools {
public static Bitmap setScaleBitmap(Bitmap photo,int SCALE) {
if (photo != null) {
//为防止原始图片过大导致内存溢出,这里先缩小原图显示,然后释放原始Bitmap占用的内存
//这里缩小了1/2,但图片过大时仍然会出现加载不了,但系统中一个BITMAP最大是在10M左右,我们可以根据BITMAP的大小
//根据当前的比例缩小,即如果当前是15M,那如果定缩小后是6M,那么SCALE= 15/6
Bitmap smallBitmap = zoomBitmap(photo, photo.getWidth() / SCALE, photo.getHeight() / SCALE);
//释放原始图片占用的内存,防止out of memory异常发生
//photo.recycle();
return smallBitmap;
}
return null;
}
// 利用矩阵进行缩放不会造成内存溢出
public static Bitmap zoomBitmap(Bitmap bitmap, int width, int height) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();
Matrix matrix = new Matrix();
float scaleWidth = ((float) width / w);
float scaleHeight = ((float) height / h);
matrix.postScale(scaleWidth, scaleHeight);// 利用矩阵进行缩放不会造成内存溢出
Bitmap newbmp = Bitmap.createBitmap(bitmap, 0, 0, w, h, matrix, true);
return newbmp;
}
public static void savePhotoToSDCard(Bitmap photoBitmap,String path,String photoName){
if (checkSDCardAvailable()) {
File dir = new File(path);
if (!dir.exists()){
dir.mkdirs();
}
File photoFile = new File(path , photoName + ".png");
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(photoFile);
if (photoBitmap != null) {
if (photoBitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream)) {
fileOutputStream.flush();
// fileOutputStream.close();
}
}
} catch (FileNotFoundException e) {
photoFile.delete();
e.printStackTrace();
} catch (IOException e) {
photoFile.delete();
e.printStackTrace();
} finally{
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static boolean checkSDCardAvailable(){
return android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);
}
/**
* Get images from SD card by path and the name of image
* @param photoName
* @return
*/
public static Bitmap getPhotoFromSDCard(String path,String photoName){
Bitmap photoBitmap = BitmapFactory.decodeFile(path + "/" +photoName);
if (photoBitmap == null) {
return null;
}else {
return photoBitmap;
}
}
/**
* Get image from SD card by path and the name of image
* @param fileName
* @return
*/
public static boolean findPhotoFromSDCard(String path,String photoName){
boolean flag = false;
if (checkSDCardAvailable()) {
File dir = new File(path);
if (dir.exists()) {
File folders = new File(path);
File photoFile[] = folders.listFiles();
for (int i = 0; i < photoFile.length; i++) {
String fileName = photoFile[i].getName().split("\\.")[0];
if (fileName.equals(photoName)) {
flag = true;
}
}
}else {
flag = false;
}
// File file = new File(path + "/" + photoName + ".jpg" );
// if (file.exists()) {
// flag = true;
// }else {
// flag = false;
// }
}else {
flag = false;
}
return flag;
}
public static void deletePhotoAtPathAndName(String path,String fileName){
if (checkSDCardAvailable()) {
File folder = new File(path);
File[] files = folder.listFiles();
for (int i = 0; i < files.length; i++) {
if (files[i].getName().split("\\.")[0].equals(fileName)) {
files[i].delete();
}
}
}
}
}
package com.example.getpicture_fromlocaloropencamera;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
public class MainActivity extends Activity implements OnClickListener{
private Button openLocalPicture_bt;
private Button openCamera_bt;
private ImageView userhead_iv;
private static final int REQUEST_CODE_IMAGE=0;
private static final int REQUEST_CODE_CAMERA=1;
private static final int MySCALE = 5;//照片缩小比例
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
openLocalPicture_bt = (Button) findViewById(R.id.openLocalPicture_bt);
openCamera_bt = (Button) findViewById(R.id.openCamera_bt);
userhead_iv = (ImageView) findViewById(R.id.userhead_iv);
openCamera_bt.setOnClickListener(this);
openLocalPicture_bt.setOnClickListener(this);
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.openCamera_bt:
Intent getImageByCameraIntent = new Intent("android.media.action.IMAGE_CAPTURE");
//或者Intent openCameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//
//1.拍照时,将拍到原图照片先保存在本地,不然通过onActivityResult方法里Intent的getData方法获取只是缩略图,得不到原图
//指定照片保存路径(SD卡),image.jpg为一个临时文件,每次拍照后这个图片都会被替换
Uri imageUri = Uri.fromFile(new File(Environment.getExternalStorageDirectory(),"image.jpg"));
getImageByCameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(getImageByCameraIntent, REQUEST_CODE_CAMERA);
break;
case R.id.openLocalPicture_bt:
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");//相片类型
startActivityForResult(intent, REQUEST_CODE_IMAGE);
break;
default:
break;
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
if (resultCode == RESULT_OK) {
switch (requestCode) {
case REQUEST_CODE_IMAGE:
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.setScaleBitmap(photo, MySCALE);
//由于Bitmap内存占用较大,这里需要回收内存,否则会报out of memory异常
//释放原始图片占用的内存,防止out of memory异常发生
photo.recycle();
userhead_iv.setImageBitmap(smallBitmap);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
break;
case REQUEST_CODE_CAMERA:
//将保存在本地的图片取出并缩小后显示在界面上
//Bitmap bitmap = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory()+"/image.jpg");
//或者使用
Bitmap bitmap = ImageTools.getPhotoFromSDCard(Environment.getExternalStorageDirectory()+"", "image.jpg");
Bitmap newBitmap = ImageTools.setScaleBitmap(bitmap, MySCALE);
//由于Bitmap内存占用较大,这里需要回收内存,否则会报out of memory异常
// bitmap.recycle();//setScaleBitmap(bitmap, MySCALE);中已经释放过了这里不需要了
//将处理过的图片显示在界面上,并保存到本地
userhead_iv.setImageBitmap(newBitmap);
ImageTools.savePhotoToSDCard(newBitmap, Environment.getExternalStorageDirectory().getAbsolutePath(), String.valueOf(System.currentTimeMillis()));
break;
default:
break;
}
}
super.onActivityResult(requestCode, resultCode, data);
}
}