获取本地图片或拍照并保存到本地

在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();
				}
			}
		}
	}

}



MainActivity

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);
	}



}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值