Android中拍照和选择图片的处理

今天总结一下,在我们APP中拍照和选择图片的相关处理。

拍照ACTION:

MediaStore.ACTION_IMAGE_CAPTURE

启用相册ACTION:

Intent.ACTION_GET_CONTENT

裁剪ACTION:

com.android.camera.action.CROP 

我们使用系统自带的Activity就行拍照、裁剪的话,肯定是使用隐式的Intent。可配置的参数如下:

附加选项	数据类型	描述
crop	String	发送裁剪信号
aspectX	int	X方向上的比例
aspectY	int	Y方向上的比例
outputX	int	裁剪区的宽
outputY	int	裁剪区的高
scale	boolean	是否保留比例
return-data	boolean	是否将数据保留在Bitmap中返回
data	Parcelable	相应的Bitmap数据
circleCrop	String	圆形裁剪区域?
MediaStore.EXTRA_OUTPUT ("output")	URI	将URI指向相应的file:///...,详见代码示例
outputFormat	String	输出格式,一般设为Bitmap格式:Bitmap.CompressFormat.JPEG.toString()
noFaceDetection	boolean	是否取消人脸识别功能


这里要分以下几种情况:

1. 直接启动系统拍照的activity,在onActivityResult中获取到data数据,这个数据其实就是bitmap,当然启动的intent中,return-data设置为true,但是这样也是有问题的,如果data数据太多,bitmap只能是一个缩略图。

2. 启动拍照的activity的intent,设置return-data为false,并且指定MediaStore.EXTRA_OUTPUT,即图片的存放路径,这样在onActivityResult中,根据指定的位置拿到图片。

3. 启动拍照的act时,同时让其进行裁剪,这样的话,很容易出问题,当图片比较大时,拍照界面将数据传递给裁剪界面时,就会出现崩溃。

4. 拍照和裁剪分成两个步骤进行,在onActivityResult处理返回结果.


这里要特别注意第四种情况,在指定拍照的图片的存放路径时,会出现图片旋转90度的情况,最后发现是我在指定拍照返回的路径Uri时图片的后缀是png,我改成jpg以后,就没有出现旋转90度的情况,我的手机是node3,

其他的机型还没有验证。针对这个问题我做了延伸,如果确实是图片旋转了90度,我的处理思路是可以先将拍照的图片,先旋转90度,然后存放在sd路径中,裁剪时是依据新保存的这个图片,但是这样以来,很容易导致图片OOM。


以上是针对拍照。


下面我们说说选择系统相册中的图片的几种情况:

1. 从相册中直接选取,在onActivityResult中intent的getData获取路径信息

2. 从相册中直接选择,在onactivityresult中intent的data获取到图片的路径信息,通过路径信息获取到Uri,转成bitmap(这种方式很多的开源项目都在用)。

3. 从相册中选择的同时并裁剪,图片比较大时,就会出现奔溃,还是两个界面传递数据的问题。

4. 先从相册中选取图片,然后再进行裁剪,是比较理想的情况。


从相册中选择图片时,在onActivityResult中如何从data中图片对应路径信息呢?

if (data != null) {
                Uri selectedImg = data.getData();
                if (selectedImg != null) {
                    String[] filePathColumn = { MediaStore.Images.Media.DATA };
                    Cursor cursor = this.getContentResolver().query(selectedImg, filePathColumn, null, null, null);
                    if (null == cursor) {
                        String path = selectedImg.getPath();
                        File file = new File(path);
                        if (file.isFile()) {
                            copyAndCrop(file);
                            return;
                        } else {
                            Toast.makeText(this, this.getString(R.string.picture_not_found),Toast.LENGTH_SHORT).show();
                            return;
                        }
                    } else if (!cursor.moveToFirst()) {
                        Toast.makeText(this, this.getString(R.string.picture_not_found),Toast.LENGTH_SHORT).show();
                        return;
                    }
                    int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
                    String path = cursor.getString(columnIndex);
                    if (path != null) {
                        File file = new File(path);
                        if (!file.isFile()) {
                            Toast.makeText(this, this.getString(R.string.picture_not_found),
                                    Toast.LENGTH_SHORT).show();
                            cursor.close();
                        } else {
                            //如果是选择本地图片进行头像设置,复制到临时文件,并进行裁剪
                            copyAndCrop(file);
                            cursor.close();
                        }
                    }
                }
            }

终极解决方案为第四种

接下来会考虑拍摄图片太大时,如何防止图片OOM的情况.


图片的压缩和旋转处理:

public static Bitmap revitionImage(String path) throws IOException {
        if (null == path || TextUtils.isEmpty(path) || !new File(path).exists())
            return null;
        BufferedInputStream in = null;
        try {
            // 获取到图片的旋转属性
            int degree = readPictureDegree(path);
            in = new BufferedInputStream(new FileInputStream(new File(path)));
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(in, null, options);
            // 计算出图片的缩放比例
            options.inSampleSize = calculateInSampleSize(options, 400, 600);
            
            in.close();
            in = new BufferedInputStream(new FileInputStream(new File(path)));
            options.inJustDecodeBounds = false;
            Bitmap bitmap = BitmapFactory.decodeStream(in, null, options);
            Bitmap newbitmap = rotaingImageView(degree, bitmap);
            return newbitmap;
        } catch (Exception e) {
            Logger.getLogger(PhotoHelper.class).e(e.getMessage());
            return null;
        } finally {
            if (null != in) {
                in.close();
                in = null;
            }
        }
    }

public static int readPictureDegree(String path) {
        int degree = 0;
        try {
            ExifInterface exifInterface = new ExifInterface(path);
            int orientation = exifInterface.getAttributeInt(
                    ExifInterface.TAG_ORIENTATION,
                    ExifInterface.ORIENTATION_NORMAL);
            switch (orientation) {
                case ExifInterface.ORIENTATION_ROTATE_90:
                    degree = 90;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    degree = 180;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    degree = 270;
                    break;
            }
        } catch (IOException e) {
            Logger.getLogger(PhotoHelper.class).e(e.getMessage());
        }
        return degree;
    }
public static int calculateInSampleSize(BitmapFactory.Options options,  
            int reqWidth, int reqHeight) {  
        // 源图片的高度和宽度  
        final int height = options.outHeight;  
        final int width = options.outWidth;  
        int inSampleSize = 1;  
        if (height > reqHeight || width > reqWidth) {  
            // 计算出实际宽高和目标宽高的比率  
            final int heightRatio = Math.round((float) height / (float) reqHeight);  
            final int widthRatio = Math.round((float) width / (float) reqWidth);  
            // 选择宽和高中最小的比率作为inSampleSize的值,这样可以保证最终图片的宽和高  
            // 一定都会大于等于目标的宽和高。  
            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;  
        }  
        return inSampleSize;  
    }  

public static Bitmap rotaingImageView(int angle, Bitmap bitmap) {
        if (null == bitmap) {
            return null;
        }
        // 旋转图片 动作
        Matrix matrix = new Matrix();
        matrix.postRotate(angle);
        // 创建新的图片
        Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0,
                bitmap.getWidth(), bitmap.getHeight(), matrix, true);
        return resizedBitmap;
    }









  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Unity,我们可以使用Android原生功能来打开图片拍照。要实现这些功能,我们可以使用Android的Intent来启动系统的图片选择器或相机应用。 首先,要打开图片,我们需要使用Intent来启动图片选择器应用。我们可以使用如下代码: ```csharp AndroidJavaClass intentClass = new AndroidJavaClass("android.content.Intent"); AndroidJavaObject intentObject = new AndroidJavaObject("android.content.Intent", intentClass.GetStatic<string>("ACTION_PICK")); intentObject.Call<AndroidJavaObject>("setType", "image/*"); intentObject.Call<AndroidJavaObject>("putExtra", intentClass.GetStatic<string>("EXTRA_ALLOW_MULTIPLE"), true); AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); AndroidJavaObject unityActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity"); unityActivity.Call("startActivityForResult", intentObject, PICK_IMAGE_REQUEST); ``` 而要拍照,我们可以使用如下代码: ```csharp AndroidJavaClass intentClass = new AndroidJavaClass("android.content.Intent"); AndroidJavaObject intentObject = new AndroidJavaObject("android.content.Intent", intentClass.GetStatic<string>("MediaStore.ACTION_IMAGE_CAPTURE")); AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); AndroidJavaObject unityActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity"); unityActivity.Call("startActivityForResult", intentObject, TAKE_PHOTO_REQUEST); ``` 在以上代码,我们使用AndroidJavaClass和AndroidJavaObject来创建一个新的Intent对象,然后启动系统的图片选择器或相机应用。最后,我们需要在Unity的```OnActivityResult```方法处理返回的结果,来获取选择图片或拍摄的照片。 需要注意的是,我们需要在AndroidManifest.xml文件添加相应的权限声明,例如读取外部存储的权限和相机权限,以确保应用能够正常打开图片拍照

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值