zoukankan      html  css  js  c++  java
  • android选择和裁剪图像拍摄的图像

            转载请注明出处:http://blog.csdn.net/allen315410/article/details/39994913

            近期从曾经的项目中扒下来一个经常使用的模块。在这里有必要记录一下的。就是android上获取图片以及裁剪图片,怎么样?这个功能是不是非经常常使用啊,你随便打开一个App。仅仅要它有注冊功能都会有设置人物头像的功能,尤其在内容型的app中更为常见,那么这些功能是怎么实现的呢?今天,在这里就记录一下好了。防止以后的项目中也会用到,就直接拿来用好了。

    1.通过拍照或者图冊获取图片(不须要剪裁)

            这样的获取图片的方式就比較次了,由于不设置图片的剪裁功能,有可能由于图片过大。导致OOM。可是这样的方式也是有必要讲一下的,其获取图片的方式有两种。一是调用系统相机实时拍摄一张图片,二十打开设备上已有的图库。在图库中选择一张照片。这两种方式实现方法都是一个道理,无非就是通过Intent调用系统的东西。以下是源代码,首先是图片选择方式的Activity,这个Activity被设置成了Dialog模式,须要进行设置一下。

    布局文件/res/layout/activity_select_photo.xml:

    <?xml version="1.0" encoding="utf-8"?

    > <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" > <LinearLayout android:id="@+id/dialog_layout" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_marginLeft="10dip" android:layout_marginRight="10dip" android:gravity="center_horizontal" android:orientation="vertical" > <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@drawable/select_photo_up_bg" android:orientation="vertical" android:paddingBottom="5dp" android:paddingTop="5dp" > <Button android:id="@+id/btn_take_photo" android:layout_width="fill_parent" android:layout_height="35dp" android:background="@drawable/select_photo_bg" android:text="拍照选取" android:textStyle="bold" /> <View android:layout_width="fill_parent" android:layout_height="0.5px" android:background="#828282" /> <Button android:id="@+id/btn_pick_photo" android:layout_width="fill_parent" android:layout_height="35dp" android:layout_marginTop="0dip" android:background="@drawable/select_photo_bg" android:text="相冊选取" android:textStyle="bold" /> </LinearLayout> <Button android:id="@+id/btn_cancel" android:layout_width="fill_parent" android:layout_height="35dp" android:layout_marginTop="20dip" android:background="@drawable/select_photo_bg" android:paddingBottom="5dp" android:paddingTop="5dp" android:text="取消" android:textColor="#ffff0000" android:textStyle="bold" /> </LinearLayout> </RelativeLayout>

    接着是获取图片Activity里的代码SelectPhotoActivity:

    public class SelectPhotoActivity extends Activity implements OnClickListener {
    	/** 使用照相机拍照获取图片 */
    	public static final int SELECT_PIC_BY_TACK_PHOTO = 1;
    	/** 使用相冊中的图片 */
    	public static final int SELECT_PIC_BY_PICK_PHOTO = 2;
    	/** 开启相机 */
    	private Button btn_take_photo;
    	/** 开启图冊 */
    	private Button btn_pick_photo;
    	/** 取消 */
    	private Button btn_cancel;
    	/** 获取到的图片路径 */
    	private String picPath;
    	private Intent lastIntent;
    	private Uri photoUri;
    	/** 从Intent获取图片路径的KEY */
    	public static final String KEY_PHOTO_PATH = "photo_path";
    
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_select_photo);
    		btn_take_photo = (Button) findViewById(R.id.btn_take_photo);
    		btn_pick_photo = (Button) findViewById(R.id.btn_pick_photo);
    		btn_cancel = (Button) findViewById(R.id.btn_cancel);
    
    		lastIntent = getIntent();
    
    		btn_take_photo.setOnClickListener(this);
    		btn_pick_photo.setOnClickListener(this);
    		btn_cancel.setOnClickListener(this);
    	}
    
    	@Override
    	public void onClick(View v) {
    		switch (v.getId()) {
    			case R.id.btn_take_photo : // 开启相机
    				takePhoto();
    				break;
    			case R.id.btn_pick_photo : // 开启图冊
    				pickPhoto();
    				break;
    			case R.id.btn_cancel : // 取消操作
    				this.finish();
    				break;
    			default :
    				break;
    		}
    	}
    
    	/**
    	 * 拍照获取图片
    	 */
    	private void takePhoto() {
    		// 运行拍照前,应该先推断SD卡是否存在
    		String SDState = Environment.getExternalStorageState();
    		if (SDState.equals(Environment.MEDIA_MOUNTED)) {
    			Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);// "android.media.action.IMAGE_CAPTURE"
    			/***
    			 * 须要说明一下,下面操作使用照相机拍照,拍照后的图片会存放在相冊中的 这里使用的这样的方式有一个优点就是获取的图片是拍照后的原图
    			 * 假设不有用ContentValues存放照片路径的话。拍照后获取的图片为缩略图不清晰
    			 */
    			ContentValues values = new ContentValues();
    			photoUri = this.getContentResolver().insert(
    					MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
    			intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, photoUri);
    			startActivityForResult(intent, SELECT_PIC_BY_TACK_PHOTO);
    		} else {
    			Toast.makeText(getApplicationContext(), "内存卡不存在",
    					Toast.LENGTH_SHORT).show();
    		}
    	}
    
    	/***
    	 * 从相冊中取图片
    	 */
    	private void pickPhoto() {
    		Intent intent = new Intent();
    		intent.setType("image/*");
    		intent.setAction(Intent.ACTION_GET_CONTENT);
    		startActivityForResult(intent, SELECT_PIC_BY_PICK_PHOTO);
    	}
    
    	@Override
    	public boolean onTouchEvent(MotionEvent event) {
    		finish();
    		return super.onTouchEvent(event);
    	}
    
    	@Override
    	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    		if (resultCode == Activity.RESULT_OK) {
    			doPhoto(requestCode, data);
    		}
    		super.onActivityResult(requestCode, resultCode, data);
    	}
    
    	/**
    	 * 选择图片后。获取图片的路径
    	 * 
    	 * @param requestCode
    	 * @param data
    	 */
    	private void doPhoto(int requestCode, Intent data) {
    		if (requestCode == SELECT_PIC_BY_PICK_PHOTO) {// 从相冊取图片,有些手机有异常情况,请注意
    			if (data == null) {
    				Toast.makeText(getApplicationContext(), "选择图片文件出错",
    						Toast.LENGTH_SHORT).show();
    				return;
    			}
    			photoUri = data.getData();
    			if (photoUri == null) {
    				Toast.makeText(getApplicationContext(), "选择图片文件出错",
    						Toast.LENGTH_SHORT).show();
    				return;
    			}
    		}
    		String[] pojo = {MediaStore.Images.Media.DATA};
    		Cursor cursor = managedQuery(photoUri, pojo, null, null, null);
    		if (cursor != null) {
    			int columnIndex = cursor.getColumnIndexOrThrow(pojo[0]);
    			cursor.moveToFirst();
    			picPath = cursor.getString(columnIndex);
    			cursor.close();
    		}
    		if (picPath != null
    				&& (picPath.endsWith(".png") || picPath.endsWith(".PNG")
    						|| picPath.endsWith(".jpg") || picPath.endsWith(".JPG"))) {
    			lastIntent.putExtra(KEY_PHOTO_PATH, picPath);
    			setResult(Activity.RESULT_OK, lastIntent);
    			finish();
    		} else {
    			Toast.makeText(getApplicationContext(), "选择图片文件不对",
    					Toast.LENGTH_SHORT).show();
    		}
    	}
    
    }
    由于这Activity是要设置成Dialog模式的,所以须要在清单文件里设置一下style,/res/values/styles.xml里加入例如以下:

    <!-- 选取照片的Activity的样式风格,採取对话框的风格 -->
        <style name="AnimBottom" parent="@android:style/Animation">
            <item name="android:windowEnterAnimation">@anim/push_bottom_in</item>
            <item name="android:windowExitAnimation">@anim/push_bottom_out</item>
        </style>
    
        <style name="DialogStyleBottom" parent="android:Theme.Dialog">
            <item name="android:windowAnimationStyle">@style/AnimBottom</item>
            <item name="android:windowFrame">@null</item>
            <!-- 边框 -->
            <item name="android:windowIsFloating">false</item>
            <!-- 是否浮如今activity之上 -->
            <item name="android:windowIsTranslucent">true</item>
            <!-- 半透明 -->
            <item name="android:windowNoTitle">true</item>
            <!-- 无标题 -->
            <item name="android:windowBackground">@android:color/transparent</item>
            <!-- 背景透明 -->
            <item name="android:backgroundDimEnabled">true</item>
            <!-- 模糊 -->
        </style>
    在Activity的节点下。设置这个style:

    <activity
                android:name="com.example.croppictrue.SelectPhotoActivity"
                android:screenOrientation="portrait"
                android:theme="@style/DialogStyleBottom" >
            </activity>
    加入权限:

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    执行效果例如以下:

       

    2.通过拍照或者图冊获取图片(须要剪裁)

          上面第一种方式获取图片是没有经过剪裁的,可是大多项目需求是须要剪裁图片后再使用,比如改动用户头像等等功能。那么,以下,就奉上剪裁图片的代码吧:

    public class CropPictureActivity extends Activity {
    
    	/** ImageView对象 */
    	private ImageView iv_photo;
    	private String[] items = new String[]{"选择本地图片", "拍照"};
    	/** 头像名称 */
    	private static final String IMAGE_FILE_NAME = "image.jpg";
    
    	/** 请求码 */
    	private static final int IMAGE_REQUEST_CODE = 0;
    	private static final int CAMERA_REQUEST_CODE = 1;
    	private static final int RESULT_REQUEST_CODE = 2;
    
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_crop);
    		iv_photo = (ImageView) findViewById(R.id.iv_photo);
    		iv_photo.setOnClickListener(new OnClickListener() {
    
    			@Override
    			public void onClick(View v) {
    				showDialog();
    			}
    		});
    	}
    
    	/**
    	 * 显示选择对话框
    	 */
    	private void showDialog() {
    
    		new AlertDialog.Builder(this)
    				.setTitle("设置头像")
    				.setItems(items, new DialogInterface.OnClickListener() {
    
    					@Override
    					public void onClick(DialogInterface dialog, int which) {
    						switch (which) {
    							case 0 :
    								Intent intentFromGallery = new Intent();
    								intentFromGallery.setType("image/*"); // 设置文件类型
    								intentFromGallery
    										.setAction(Intent.ACTION_GET_CONTENT);
    								startActivityForResult(intentFromGallery,
    										IMAGE_REQUEST_CODE);
    								break;
    							case 1 :
    								Intent intentFromCapture = new Intent(
    										MediaStore.ACTION_IMAGE_CAPTURE);
    								// 推断存储卡能否够用,可用进行存储
    								String state = Environment
    										.getExternalStorageState();
    								if (state.equals(Environment.MEDIA_MOUNTED)) {
    									File path = Environment
    											.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
    									File file = new File(path, IMAGE_FILE_NAME);
    									intentFromCapture.putExtra(
    											MediaStore.EXTRA_OUTPUT,
    											Uri.fromFile(file));
    								}
    
    								startActivityForResult(intentFromCapture,
    										CAMERA_REQUEST_CODE);
    								break;
    						}
    					}
    				})
    				.setNegativeButton("取消", new DialogInterface.OnClickListener() {
    
    					@Override
    					public void onClick(DialogInterface dialog, int which) {
    						dialog.dismiss();
    					}
    				}).show();
    
    	}
    
    	@Override
    	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    		// 结果码不等于取消时候
    		if (resultCode != RESULT_CANCELED) {
    			switch (requestCode) {
    				case IMAGE_REQUEST_CODE :
    					startPhotoZoom(data.getData());
    					break;
    				case CAMERA_REQUEST_CODE :
    					// 推断存储卡能否够用,可用进行存储
    					String state = Environment.getExternalStorageState();
    					if (state.equals(Environment.MEDIA_MOUNTED)) {
    						File path = Environment
    								.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
    						File tempFile = new File(path, IMAGE_FILE_NAME);
    						startPhotoZoom(Uri.fromFile(tempFile));
    					} else {
    						Toast.makeText(getApplicationContext(),
    								"未找到存储卡,无法存储照片!", Toast.LENGTH_SHORT).show();
    					}
    					break;
    				case RESULT_REQUEST_CODE : // 图片缩放完毕后
    					if (data != null) {
    						getImageToView(data);
    					}
    					break;
    			}
    		}
    		super.onActivityResult(requestCode, resultCode, data);
    	}
    
    	/**
    	 * 裁剪图片方法实现
    	 * 
    	 * @param uri
    	 */
    	public void startPhotoZoom(Uri uri) {
    		Intent intent = new Intent("com.android.camera.action.CROP");
    		intent.setDataAndType(uri, "image/*");
    		// 设置裁剪
    		intent.putExtra("crop", "true");
    		// aspectX aspectY 是宽高的比例
    		intent.putExtra("aspectX", 1);
    		intent.putExtra("aspectY", 1);
    		// outputX outputY 是裁剪图片宽高
    		intent.putExtra("outputX", 340);
    		intent.putExtra("outputY", 340);
    		intent.putExtra("return-data", true);
    		startActivityForResult(intent, RESULT_REQUEST_CODE);
    	}
    
    	/**
    	 * 保存裁剪之后的图片数据
    	 * 
    	 * @param picdata
    	 */
    	private void getImageToView(Intent data) {
    		Bundle extras = data.getExtras();
    		if (extras != null) {
    			Bitmap photo = extras.getParcelable("data");
    			Drawable drawable = new BitmapDrawable(this.getResources(), photo);
    			iv_photo.setImageDrawable(drawable);
    		}
    	}
    }
    效果图:

         

            在这个Activity里为了简便处理,我没有在选择图片时候start一个Dialog风格的Activity了,就直接一个普通的对话框提示用户选择,效果或许。事实上实现的原理都比較简单,实现图片的剪裁就是发一个Intent请求,调用设备上全部具有剪裁图片功能的app去剪裁图片,我的设备上除了android系统自带的图库以外。还装有“快图浏览”这个app,这个app也自带一个图片剪裁的功能,全部当选择好图片后,会出现一个选择提示。用户能够依据提示选择究竟使用哪个app提供的剪裁功能区剪裁图片。
            以上代码均在模拟器上測试过。因为模拟器对相机支持的不好,所以就没有演示打开相机拍摄图片了。有兴趣的朋友能够先请下载这个Demo的源代码,执行在手机上试试看效果怎样,如若疏漏之后。欢迎大家批评指正!


    源代码请在这里下载


    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    cmanformat
    mysql-sql语言参考
    jQuery 判断多个 input checkbox 中至少有一个勾选
    Java实现 蓝桥杯 算法提高 计算行列式
    Java实现 蓝桥杯 数独游戏
    Java实现 蓝桥杯 数独游戏
    Java实现 蓝桥杯 数独游戏
    Java实现 蓝桥杯 算法提高 成绩排序2
    Java实现 蓝桥杯 算法提高 成绩排序2
    Java实现 蓝桥杯 算法提高 成绩排序2
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/4665114.html
Copyright © 2011-2022 走看看