拍照、相册及裁剪的终极实现(一)

cropString发送裁剪信号

aspectXintX方向上的比例

aspectYintY方向上的比例

outputXint裁剪区的宽

outputYint裁剪区的高

scaleboolean是否保留比例

return-databoolean是否将数据保留在Bitmap中返回

dataParcelable相应的Bitmap数据

circleCropString圆形裁剪区域?

MediaStore.EXTRA_OUTPUT ("output")URI将URI指向相应的file:///…,详见代码示例

outputFormatString输出格式,一般设为Bitmap格式:Bitmap.CompressFormat.JPEG.toString()

noFaceDetectionboolean是否取消人脸识别功能

这些参数是可以选择性使用的,想使用哪个功能就直接写上,不使用就不写,下面我们就一个个试试。这里我会始终将return_data设为false,因为如何设为TRUE,那对于有些手机而言,只会得到缩略图,所以这里一致用URI来输出。而URI在有些手机上也是存在问题的,这里先不谈,先用URI,因为这是网上一致认为的终极方案………………

写在前面:

由于我们会读写SD卡,所以先在AndroidManifest.xml中添加上SD卡的读写权限:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />二、仅拍照(1)、核心代码:

我们仅仅使用拍照的功能,而且将其输出到URI中,代码如下:

启用拍照Activity

private static final int RESULT_CAMERA_ONLY = 100;

先构造一个temp.jpg的URI

String path = getSDCardPath();File file = new File(path + "/temp.jpg");imageUri = Uri.fromFile(file);然后通过MediaStore.ACTION_IMAGE_CAPTURE来隐式调起拍照Intent;

然后将返回值设为false,并将MediaStore.EXTRA_OUTPU输出指定为 imageUri;

然后将URI的输出格式设为JPEG,这是因为我们在构造URI时,使用的JPG格式:temp.jpg

Intent intent = null;intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);intent.putExtra("return-data", false);intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());intent.putExtra("noFaceDetection", true);startActivityForResult(intent, RESULT_CAMERA_ONLY);

大家可能对return-data和MediaStore.EXTRA_OUTPUT的作用有些迷糊;

在onActivityResult中接收:protected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (resultCode != Activity.RESULT_OK)return;switch (requestCode) {case RESULT_CAMERA_ONLY: {try {Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));mImage.setImageBitmap(bitmap);} catch (Exception e) {e.printStackTrace();}}break;}}将接收到的ImageUri解析为Bitmap,因为我们的URI本来就是个Bitmap,然后将其设置到一个ImageView中显示;

但在有的手机中ImageView并不会显示这个Bitmap,而查看根目录下的temp.jpg确实已经生成了。这是为什么?查看日志,报了个错:

Bitmap too large to be uploaded into a texture (3120×4160, max=4096×4096)这是因为Bitmap太大了,超出了ImageView的显示范围所致,这里有三种解决办法:

1、强制显示,关闭OpenGL加速(容易导致OOM)在AndroidManifest.xml中,application标签下添加一个属性:

android:hardwareAccelerated="false"即: <application……android:hardwareAccelerated="false"></application>2、将图片缩小

将指定图片缩小SCALE倍的代码如下:

但如果图片足够大,缩小后也不定能显示……

private Bitmap setScaleBitmap(Bitmap photo,int SCALE) {if (photo != null) {//为防止原始图片过大导致内存溢出,这里先缩小原图显示,然后释放原始Bitmap占用的内存//这里缩小了1/2,但图片过大时仍然会出现加载不了,但系统中一个BITMAP最大是在10M左右,我们可以根据BITMAP的大小//根据当前的比例缩小,即如果当前是15M,那如果定缩小后是6M,那么SCALE= 15/6Bitmap smallBitmap = zoomBitmap(photo, photo.getWidth() / SCALE, photo.getHeight() / SCALE);//释放原始图片占用的内存,防止out of memory异常发生photo.recycle();return smallBitmap;}return null;}public 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;}3、分块显示看这里《解决:Bitmap too large to be uploaded into a texture exception》(2)、实例

效果图:

点击按钮调起系统相册拍照,然后显示在ImageView中

要克服生活的焦虑和沮丧,得先学会做自己的主人

拍照、相册及裁剪的终极实现(一)

相关文章:

你感兴趣的文章:

标签云: