码迷,mamicode.com
首页 > 移动开发 > 详细

安卓 调用系统相机并裁剪

时间:2015-10-20 11:54:36      阅读:243      评论:0      收藏:0      [点我收藏+]

标签:

做程序猿已有一段时间,东西也做了挺多,今天刚开通了博客,把我之前做过的东西记录下来,今天先写安卓系统下调用系统照相机并裁剪

之前做调用系统相机的时候遇到过很多问题,现在贴代码,在代码中一点点提出

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方法时重新获取。

 ----------------------------------------------------------------------------

以上就是本次的所有内容了,第一次写博客没有经验,不足之处还望指正^_^

安卓 调用系统相机并裁剪

标签:

原文地址:http://www.cnblogs.com/1406675711blog/p/4892932.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!