当前位置: 移动技术网 > IT编程>移动开发>Android > Android拍照或从图库选择图片并裁剪

Android拍照或从图库选择图片并裁剪

2019年07月24日  | 移动技术网IT编程  | 我要评论

郭杰学历,凤凰山庄游戏,杨秀惠初恋

今天看《第一行代码》上面关于拍照和从相册选取图片那一部分,发现始终出不来效果,所以搜索其他资料学习一下相关知识,写一个简单的demo。 

一、 拍照选择图片

1、使用隐式intent启动相机

//构建隐式intent
intent intent = new intent(mediastore.action_image_capture);
//调用系统相机
startactivityforresult(intent, 1);

2、处理相机拍照返回的结果

//用户点击了取消
if(data == null){
  return;
}else{
  bundle extras = data.getextras();
  if (extras != null){
    //获得拍的照片
    bitmap bm = extras.getparcelable("data");
  }
}

二、 从图库选择图片

1、构建内容选择隐式intent

intent intent = new intent(intent.action_get_content);

2、设置内容类型为图片

intent.settype("image/*");

3、启动图片选择

startactivityforresult(intent, 2);

4、处理图片选择结果

if (data == null){
  return;
}else{
  //用户从图库选择图片后会返回所选图片的uri
  uri uri;
  //获取到用户所选图片的uri
  uri = data.getdata();
}

三、 裁剪选择的图片

从相机拍照得到的是bitmap类型,所以我们需要先将其转化为文件uri以供裁剪。同时我们还要顺便将相机拍的照片保存到本地。

 /**
 * 将bitmap写入sd卡中的一个文件中,并返回写入文件的uri
 * @param bm
 * @param dirpath
 * @return
 */
private uri savebitmap(bitmap bm, string dirpath) {
  //新建文件夹用于存放裁剪后的图片
  file tmpdir = new file(environment.getexternalstoragedirectory() + "/" + dirpath);
  if (!tmpdir.exists()){
    tmpdir.mkdir();
  }

  //新建文件存储裁剪后的图片
  file img = new file(tmpdir.getabsolutepath() + "/avator.png");
  try {
    //打开文件输出流
    fileoutputstream fos = new fileoutputstream(img);
    //将bitmap压缩后写入输出流(参数依次为图片格式、图片质量和输出流)
    bm.compress(bitmap.compressformat.png, 85, fos);
    //刷新输出流
    fos.flush();
    //关闭输出流
    fos.close();
    //返回file类型的uri
    return uri.fromfile(img);
  } catch (filenotfoundexception e) {
    e.printstacktrace();
    return null;
  } catch (ioexception e) {
    e.printstacktrace();
    return null;
  }
}

从图库选择的图片返回的是content类型的uri,我们需要转化为文件类型的uri才能进行裁剪。

 /**
* 将content类型的uri转化为文件类型的uri
* @param uri
* @return
*/
private uri converturi(uri uri){
  inputstream is;
  try {
    //uri ----> inputstream
    is = getcontentresolver().openinputstream(uri);
    //inputstream ----> bitmap
    bitmap bm = bitmapfactory.decodestream(is);
    //关闭流
    is.close();
    return savebitmap(bm, "temp");
  } catch (filenotfoundexception e) {
    e.printstacktrace();
    return null;
  } catch (ioexception e) {
    e.printstacktrace();
    return null;
  }

}

下面便是设置裁剪的参数,用隐式intent方式启动裁剪程序

 /**
 * 通过uri传递图像信息以供裁剪
 * @param uri
 */
private void startimagezoom(uri uri){
  //构建隐式intent来启动裁剪程序
  intent intent = new intent("com.android.camera.action.crop");
  //设置数据uri和类型为图片类型
  intent.setdataandtype(uri, "image/*");
  //显示view为可裁剪的
  intent.putextra("crop", true);
  //裁剪的宽高的比例为1:1
  intent.putextra("aspectx", 1);
  intent.putextra("aspecty", 1);
  //输出图片的宽高均为150
  intent.putextra("outputx", 150);
  intent.putextra("outputy", 150);
  //裁剪之后的数据是通过intent返回
  intent.putextra("return-data", true);
  startactivityforresult(intent, crop_code);
}

下面是完整的布局文件和java文件

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

activity_main.xml文件

<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical">

  <imageview
    android:id="@+id/show_image"
    android:layout_width="match_parent"
    android:layout_height="300dp"/>
  <button
    android:id="@+id/choose_camera"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="摄像头"/>
  <button
    android:id="@+id/choose_gallery"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="相册"/>
</linearlayout>

mainactivity.java文件

public class mainactivity extends appcompatactivity implements view.onclicklistener {
  //用于展示选择的图片
  private imageview mimageview;

  private static final int camera_code = 1;
  private static final int gallery_code = 2;
  private static final int crop_code = 3;

  @override
  protected void oncreate(bundle savedinstancestate) {
    super.oncreate(savedinstancestate);
    setcontentview(r.layout.activity_main);

    initview();
  }

  private void initview() {
    mimageview = (imageview) findviewbyid(r.id.show_image);
    button choosecamera = (button) findviewbyid(r.id.choose_camera);
    choosecamera.setonclicklistener(this);
    button choosegallery = (button) findviewbyid(r.id.choose_gallery);
    choosegallery.setonclicklistener(this);
  }

  @override
  public void onclick(view view) {
    switch (view.getid()){
      case r.id.choose_camera:
        //拍照选择
        choosefromcamera();
        break;
      case r.id.choose_gallery:
        //从相册选取
        choosefromgallery();
        break;
      default:
        break;
    }
  }

  /**
   * 拍照选择图片
   */
  private void choosefromcamera() {
    //构建隐式intent
    intent intent = new intent(mediastore.action_image_capture);
    //调用系统相机
    startactivityforresult(intent, camera_code);
  }

  /**
   * 从相册选择图片
   */
  private void choosefromgallery() {
    //构建一个内容选择的intent
    intent intent = new intent(intent.action_get_content);
    //设置选择类型为图片类型
    intent.settype("image/*");
    //打开图片选择
    startactivityforresult(intent, gallery_code);
  }

  @override
  protected void onactivityresult(int requestcode, int resultcode, intent data) {
    switch (requestcode){
      case camera_code:
        //用户点击了取消
        if(data == null){
          return;
        }else{
          bundle extras = data.getextras();
          if (extras != null){
            //获得拍的照片
            bitmap bm = extras.getparcelable("data");
            //将bitmap转化为uri
            uri uri = savebitmap(bm, "temp");
            //启动图像裁剪
            startimagezoom(uri);
          }
        }
        break;
      case gallery_code:
        if (data == null){
          return;
        }else{
          //用户从图库选择图片后会返回所选图片的uri
          uri uri;
          //获取到用户所选图片的uri
          uri = data.getdata();
          //返回的uri为content类型的uri,不能进行复制等操作,需要转换为文件uri
          uri = converturi(uri);
          startimagezoom(uri);
        }
        break;
      case crop_code:
        if (data == null){
          return;
        }else{
          bundle extras = data.getextras();
          if (extras != null){
            //获取到裁剪后的图像
            bitmap bm = extras.getparcelable("data");
            mimageview.setimagebitmap(bm);
          }
        }
        break;
      default:
        break;
    }
  }

  /**
   * 将content类型的uri转化为文件类型的uri
   * @param uri
   * @return
   */
  private uri converturi(uri uri){
    inputstream is;
    try {
      //uri ----> inputstream
      is = getcontentresolver().openinputstream(uri);
      //inputstream ----> bitmap
      bitmap bm = bitmapfactory.decodestream(is);
      //关闭流
      is.close();
      return savebitmap(bm, "temp");
    } catch (filenotfoundexception e) {
      e.printstacktrace();
      return null;
    } catch (ioexception e) {
      e.printstacktrace();
      return null;
    }
  }

  /**
   * 将bitmap写入sd卡中的一个文件中,并返回写入文件的uri
   * @param bm
   * @param dirpath
   * @return
   */
  private uri savebitmap(bitmap bm, string dirpath) {
    //新建文件夹用于存放裁剪后的图片
    file tmpdir = new file(environment.getexternalstoragedirectory() + "/" + dirpath);
    if (!tmpdir.exists()){
      tmpdir.mkdir();
    }

    //新建文件存储裁剪后的图片
    file img = new file(tmpdir.getabsolutepath() + "/avator.png");
    try {
      //打开文件输出流
      fileoutputstream fos = new fileoutputstream(img);
      //将bitmap压缩后写入输出流(参数依次为图片格式、图片质量和输出流)
      bm.compress(bitmap.compressformat.png, 85, fos);
      //刷新输出流
      fos.flush();
      //关闭输出流
      fos.close();
      //返回file类型的uri
      return uri.fromfile(img);
    } catch (filenotfoundexception e) {
      e.printstacktrace();
      return null;
    } catch (ioexception e) {
      e.printstacktrace();
      return null;
    }

  }

  /**
   * 通过uri传递图像信息以供裁剪
   * @param uri
   */
  private void startimagezoom(uri uri){
    //构建隐式intent来启动裁剪程序
    intent intent = new intent("com.android.camera.action.crop");
    //设置数据uri和类型为图片类型
    intent.setdataandtype(uri, "image/*");
    //显示view为可裁剪的
    intent.putextra("crop", true);
    //裁剪的宽高的比例为1:1
    intent.putextra("aspectx", 1);
    intent.putextra("aspecty", 1);
    //输出图片的宽高均为150
    intent.putextra("outputx", 150);
    intent.putextra("outputy", 150);
    //裁剪之后的数据是通过intent返回
    intent.putextra("return-data", true);
    startactivityforresult(intent, crop_code);
  }
}

注:最后还需要在androidmanifest文件中加入存储卡读写权限

复制代码 代码如下:
<uses-permission android:name="android.permission.write_external_storage"/>
<uses-permission android:name="android.permission.read_external_storage"/>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网