博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[Android] 拍照、截图、保存并显示在ImageView控件中
阅读量:4449 次
发布时间:2019-06-07

本文共 6363 字,大约阅读时间需要 21 分钟。

    近期在做Android的项目,当中部分涉及到图像处理的内容.这里先讲述怎样调用Camera应用程序进行拍照,并截图和保存显示在ImageView控件中以及遇到的困难和解决方法.

    PS:作者购买了本《Android第一行代码 著:郭霖》,參照里面的内容完毕(推荐该书,前面的布局及应用很不错).网上这类资料许多,作者只分享给刚開始学习的人同一时候在线记录些内容,希望对大家有所帮助.
   首先,设置activity_main.xml为LinearLayout布局且 android:orientation="vertical"

   

   然后,在MainActivity.java文件中public class MainActivity extends Activity改动源码.加入自己定义变量:

//自己定义变量public static final int TAKE_PHOTO = 1;public static final int CROP_PHOTO = 2;private Button takePhotoBn;private ImageView showImage;private Uri imageUri; //图片路径private String filename; //图片名称
   加入函数实现点击拍照功能:

@Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    takePhotoBn = (Button) findViewById(R.id.button1);    showImage = (ImageView) findViewById(R.id.imageView1);    //点击"Photo Button"button照相    takePhotoBn.setOnClickListener(new OnClickListener() {    	@Override    	public void onClick(View v) {    		//图片名称 时间命名    		SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");            Date date = new Date(System.currentTimeMillis());            filename = format.format(date);    		//创建File对象用于存储拍照的图片 SD卡根文件夹               		//File outputImage = new File(Environment.getExternalStorageDirectory(),"test.jpg");    		//存储至DCIM目录    		File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);      		File outputImage = new File(path,filename+".jpg");    		try {    			if(outputImage.exists()) {     				outputImage.delete();    			}    			outputImage.createNewFile();    		} catch(IOException e) {    			e.printStackTrace();    		}    		//将File对象转换为Uri并启动照相程序    		imageUri = Uri.fromFile(outputImage);    		Intent intent = new Intent("android.media.action.IMAGE_CAPTURE"); //照相    		intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); //指定图片输出地址    		startActivityForResult(intent,TAKE_PHOTO); //启动照相    		//拍完照startActivityForResult() 结果返回onActivityResult()函数    	}    });    if (savedInstanceState == null) {        getFragmentManager().beginTransaction()                .add(R.id.container, new PlaceholderFragment())                .commit();    }}
   通过startActivityForResult和onActivityResult方法实现拍照截图和保存功能:

protected void onActivityResult(int requestCode, int resultCode, Intent data) {	super.onActivityResult(requestCode, resultCode, data);	if (resultCode != RESULT_OK) { 		Toast.makeText(MainActivity.this, "ActivityResult resultCode error", Toast.LENGTH_SHORT).show();		return; 	}	switch(requestCode) {	case TAKE_PHOTO:		Intent intent = new Intent("com.android.camera.action.CROP"); //剪裁		intent.setDataAndType(imageUri, "image/*");		intent.putExtra("scale", true);		//设置宽高比例		intent.putExtra("aspectX", 1);        intent.putExtra("aspectY", 1);        //设置裁剪图片宽高        intent.putExtra("outputX", 340);	    intent.putExtra("outputY", 340);		intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);		Toast.makeText(MainActivity.this, "剪裁图片", Toast.LENGTH_SHORT).show();		//广播刷新相冊 	    Intent intentBc = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);		intentBc.setData(imageUri);     		this.sendBroadcast(intentBc);    		startActivityForResult(intent, CROP_PHOTO); //设置裁剪參数显示图片至ImageView		break;	case CROP_PHOTO:		try {	 			//图片解析成Bitmap对象			Bitmap bitmap = BitmapFactory.decodeStream(					getContentResolver().openInputStream(imageUri));			Toast.makeText(MainActivity.this, imageUri.toString(), Toast.LENGTH_SHORT).show();			showImage.setImageBitmap(bitmap); //将剪裁后照片显示出来		} catch(FileNotFoundException e) {			e.printStackTrace();		}		break;	default:		break;	}}

    因为涉及到SD卡中写数据操作和Camera操作,须要在AndroidMainfest.xml文件里声明权限:

    执行结果例如以下图所看到的:

       

    须要注意下面几个问题:

    1.拍照和截图都涉及到startActivityForResult和onActivityResult的交互操作.

startActivityForResult(	Intent intent,   //Intent对象	int requestCode  //>=0 当Activity结束时requestCode将归还在onActivityResult()中)onActivityResult(	int requestCode,  //提供给onActivityResult,以确认返回的数据是从哪个Activity返回的	int resultCode,   //由子Activity通过其setResult()方法返回 通常为RESULT_CANCELED或RESULT_OK	Intent data       //一个Intent对象,带有返回的数据)

   当中onActivityResult的requestCode和startActivityForResult中的requestCode相相应.同一时候结合Intent意图实现拍照和截图,核心代码例如以下:(intent的參数设置省略)

    Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
    startActivityForResult(intent,TAKE_PHOTO);
    Intent intent = new Intent("com.android.camera.action.CROP"); 
    startActivityForResult(intent, CROP_PHOTO);
    2.使用Android拍照保存在系统相冊,图库不能立马显示最新照片.解决方法是发送系统内置的广播去刷新相冊实现显示.代码例如以下:

Intent intentBc = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);intentBc.setData(imageUri);     this.sendBroadcast(intentBc);

    可能你会使用以下这条广播扫描整个SD卡,但4.4已禁止这种操作:

sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse(...)))
    參考资料 
    3.当执行程序是可能会发现结果图像显示非常小,当通过一个Intent意图触发时,Camera程序不会将全尺寸图像返回给主调活动,这样须要大量的内存,而移动设备内存会有一定限制.通常Camera将在返回的意图中返回一幅非常小的缩略图,大图可能会导致OOM问题.參考:《Android多媒体开发高级编程 著:Shawn Van Every》
   
针对大图像Android提供BitmapFactory类,同意通过各种资源载入Bitmap图像.调用BitmapFactory.Options类能够定义怎样将Bitmap读入内存,当载入图像时,可设置BitmapFactory採样大小.并指定inSampleSize參数表明载入时结果Bitmap图像所占的比例.如inSampleSize=8表明产生一副大小为原始图像1/8的图像.參考以下代码:

if(resultCode==RESULT_OK) {	DisplayMetrics dm = new DisplayMetrics();	getWindowManager().getDefaultDisplay().getMetrics(dm);	int width = dm.widthPixels; //宽度	int height = dm.heightPixels ; //高度	//载入图像尺寸而不是图像本身	BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();	bmpFactoryOptions.inJustDecodeBounds = true; //bitmap为null 仅仅是把图片的宽高放在Options里     Bitmap bitmap = BitmapFactory.decodeFile(imageUri.toString(), bmpFactoryOptions);	int heightRatio = (int)Math.ceil(bmpFactoryOptions.outHeight/(float)height);	int widthRatio = (int)Math.ceil(bmpFactoryOptions.outWidth/(float)width);	//设置图片压缩比例 假设两个比例大于1 图像一边将大于屏幕	if(heightRatio>1&&widthRatio>1) {		if(heightRatio>widthRatio) {			bmpFactoryOptions.inSampleSize = heightRatio;		}		else {			bmpFactoryOptions.inSampleSize = widthRatio;		}	}	//图像真正解码	bmpFactoryOptions.inJustDecodeBounds = false;	bitmap = BitmapFactory.decodeFile(imageUri.toString(), bmpFactoryOptions);	showImage.setImageBitmap(bitmap); //将剪裁后照片显示出来	}

    4.使用nexus 4 剪裁图片后不能setImageBitmap显示在ImageView控件中,当中仅仅有保存button,没有剪裁button.測试发现没有返回RESULT_OK.这个问题不能解决.Why?

    參考:
    最后希望文章对大家有所帮助,这是我学习Android图像处理部分的基础性文章与解决过程.下载地址:
參考资料和推荐博文:(都是很不错的资料-.-)
    《Android第一行代码》著郭霖 參考8.3 调用摄像头和相冊
   
 
   
    
   
   
   
   
    Android高效载入大图、多图解决方式,有效避免程序OOM By:guolin
   
   
(By:Eastmount 2014-10-23 晚10点
)

转载于:https://www.cnblogs.com/blfbuaa/p/6768050.html

你可能感兴趣的文章
【8.0】注解方式代替映射文件
查看>>
每周总结6.2
查看>>
XCode 快捷键
查看>>
ios retina
查看>>
排列与组合
查看>>
HTML5新属性-----拖放
查看>>
动态改变背景图片2
查看>>
Node.js + Web Socket 打造即时聊天程序嗨聊
查看>>
五周第五次课(1月12日) 8.10 shell特殊符号cut命令 8.11 sort_wc_uniq命令 8.12 tee_tr_split命令 8.13 shell特殊符号...
查看>>
用 WEKA 进行数据挖掘,第 1 部分: 简介和回归(转)
查看>>
css3 做菱形
查看>>
问题处理:PROCESS一个domain节点起不来
查看>>
让你前进的8句话
查看>>
POJ 1654 Area
查看>>
Report报表学习系列五
查看>>
java.lang.ClassNotFoundException错误原因汇总
查看>>
设计模式
查看>>
【BZOJ1056】[HAOI2008]排名系统(Splay)
查看>>
kubernets之endpoints
查看>>
layui confirm
查看>>