• [Android] 拍照、截图、保存并显示在ImageView控件中


        近期在做Android的项目,当中部分涉及到图像处理的内容.这里先讲述怎样调用Camera应用程序进行拍照,并截图和保存显示在ImageView控件中以及遇到的困难和解决方法.
        PS:作者购买了本《Android第一行代码 著:郭霖》,參照里面的内容完毕(推荐该书,前面的布局及应用很不错).网上这类资料许多,作者只分享给刚開始学习的人同一时候在线记录些内容,希望对大家有所帮助.
       首先,设置activity_main.xml为LinearLayout布局且 android:orientation="vertical"

    <Button
            android:id="@+id/button1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="TakePhoto Button" />
       
    <ImageView
            android:id="@+id/imageView1"    
            android:layout_width="wrap_content"  
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal" />

       然后,在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; //图片名称
       加入函数实现点击拍照功能:

    @Override
    protected 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文件里声明权限:

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.CAMERA" /> 
        执行结果例如以下图所看到的:

           

        须要注意下面几个问题:
        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(...)))

        參考资料 http://blog.csdn.net/xiaanming/article/details/8990627
        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?


        參考:Unable to Save Photo Edits
        最后希望文章对大家有所帮助,这是我学习Android图像处理部分的基础性文章与解决过程.下载地址: http://download.csdn.net/detail/eastmount/8074833
    參考资料和推荐博文:(都是很不错的资料-.-)
        《Android第一行代码》著郭霖 參考8.3 调用摄像头和相冊
       
    android拍照图片选取与图片剪裁 By:Lee_Allen  
       
    Android_照相机Camera_调用系统照相机返回data为空 By:strawberry2013
        Android图片剪裁功能实心具体解释 By:小马
        Android开发 拍照、图片集保存照片技巧
        Android 拍照并显示在ImageView中(进阶) By:leesa
        android调动系统的照相机并把照片显示在ImageView上
        cameraintent data null in onActivityResult(int requestCode, int resultCode, Intentdata)
        Android高效载入大图、多图解决方式,有效避免程序OOM By:guolin
       
    Android相机、相冊获取图片显示并保存到SD卡 By:唐韧_Ryan
        android、获取本地图片|直接获取照相图片 By:zcljy0318

    (By:Eastmount 2014-10-23 晚10点
    http://blog.csdn.net/eastmount/)

  • 相关阅读:
    互联网行业进入规范和监管时期 大数据行业也不例外
    R语言与显著性检验学习笔记
    R语言与显著性检验学习笔记
    大数据应用向前一步是什么
    大数据应用向前一步是什么
    CAS 4.0 配置开发手冊
    WinCE隐藏显示任务栏,当任务栏隐藏时将其显示,当任务栏显示时将其隐藏(FindWindow,ShowWindow,IsWindowVisible),
    每日算法之二十六:Substring with Concatenation of All Words
    Django网站管理--ModelAdmin
    Android实战简易教程-第四十一枪(显示倒计时的Button-适用于获取验证码)
  • 原文地址:https://www.cnblogs.com/blfbuaa/p/6768050.html
Copyright © 2020-2023  润新知