做程序猿已有一段时间,东西也做了挺多,今天刚开通了博客,把我之前做过的东西记录下来,今天先写安卓系统下调用系统照相机并裁剪
之前做调用系统相机的时候遇到过很多问题,现在贴代码,在代码中一点点提出
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent;
String fileName = System.currentTimeMillis() + ".png";
logoTempPath = LOGO_BASE_PATH + fileName;
intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(LOGO_BASE_PATH, fileName)));
startActivityForResult(intent, PHOTO_CAMERA);
}
});
以上是点击某个按钮调用系统相机,在这里注意一点:
String fileName = System.currentTimeMillis() + ".png";拍出来的图片名称之所以这样来命名,是因为之前遇到过一个问题,即在拍完照之后裁剪时显示的图片是上一次拍的图片,现在更改临时文件名称随时产生。
----------------------------------------------------------------------------
if(requestCode == PHOTO_CAMERA) {//拍照获取
int angle = readPictureDegree(logoTempPath);//有些手机拍完照片之后会有旋转,此处是获取照片旋转的角度,具体方法内容在后面贴出
if(angle != 0)
rotatePhoto(angle);//获取旋转角度之后,将图片旋转回来
File file = new File(logoTempPath);
startPhotoZoom(Uri.fromFile(file));//裁剪图片,代码后面贴出
}
上面是拍照之后onActivityResult方法中获取数据并调用裁剪,上面再调用拍照的时候已经将照片储存在固定位置,所以此处直接从那个位置(logoTempPath)读取数据,不用从intent中获取
之所以这样做是因为有些手机拍照之后返回的数据会为空
----------------------------------------------------------------------------
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", 200);
intent.putExtra("outputY", 200);
intent.putExtra("return-data", false);
intent.putExtra("outputFormat", Bitmap.CompressFormat.PNG.toString());
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(LOGO_ZOOM_FILE_PATH)));
startActivityForResult(intent, PHOTO_RESULT);
}
以上是裁剪的方法,这里注意一点intent.putExtra("return-data", false);这里没有设置为true,所以在裁剪之后也不能从intent中获取数据,
之前有做过设置为true,但是有些手机拍完照之后图片占内存很大,在调用裁剪的话会报OOM,这里修改为不返回数据,而是直接将数据保存在自己设置的位置上
这样改之后就不会有oom的问题
----------------------------------------------------------------------------
if(requestCode == PHOTO_RESULT) {//裁剪之后
Bitmap bitmap = BitmapFactory.decodeFile(LOGO_ZOOM_FILE_PATH);
获取裁剪之后的图片。
-----------------------------------------------------------------------------
public 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) {
e.printStackTrace();
}
return degree;
}
获取拍照之后图片旋转的角度
----------------------------------------------------------------------------
public void rotatePhoto(int angle) {
WindowManager wm = getWindowManager();
int windowWidth = wm.getDefaultDisplay().getWidth();
int windowHeight = wm.getDefaultDisplay().getHeight();
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile(logoTempPath, opts);
opts.inPreferredConfig = Bitmap.Config.RGB_565;
int bitmapHeight = opts.outHeight;
int bitmapWidth = opts.outWidth;
if (bitmapHeight > windowHeight || bitmapWidth > windowWidth) {
int scaleX = bitmapWidth / windowWidth;
int scaleY = bitmapHeight / windowHeight;
if(scaleX > scaleY)//按照水平方向的比例缩放
opts.inSampleSize = scaleX;
else //按照竖直方向的比例缩放
opts.inSampleSize = scaleY;
} else {//图片比手机屏幕小 不缩放
opts.inSampleSize = 1;
}
opts.inJustDecodeBounds = false;
Matrix m = new Matrix();
m.postRotate(angle);
Bitmap bitmap = null;
try {
bitmap = BitmapFactory.decodeFile(logoTempPath, opts);
if(bitmap == null)
return;
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), m, true);// 重新生成图片
saveToFile(bitmap);//将新生成的图片保存的指定位置,以供后面裁剪时调用,具体代码就不贴出了
} catch (OutOfMemoryError e) {
System.gc();
} finally {
if(bitmap != null)
bitmap.recycle();
}
}
以上是讲旋转的图片再转回去生成新的图片,保存到指定位置
----------------------------------------------------------------------------
最后再讲一个我最近遇到的问题,问题描述如下:
调用相机之后按home键退出程序,在手机上打开照相机拍几张照片,退出照相机重新进入程序,这时点击拍照确认键,跳转到裁剪界面时界面是黑的,没有任何照片显示。
经过一个下午的排查,最终找到原因,操作这个步骤之后,之前调用裁剪时保存的图片位置及名称已经不存在了即logoTempPath 在返回程序时已经为空了,而且本程序的这个activity重新走了onCreate方法,
所以在程序中logoTempPath为空,解决方法:
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("logoTempPath", logoTempPath);
}
将之前设置的信息保存,在下次进入本程序的onCreate方法时重新获取。
----------------------------------------------------------------------------
以上就是本次的所有内容了,第一次写博客没有经验,不足之处还望指正^_^