欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2024-03-06 19:37:38
今天看《第一行代码》上面关于拍照和从相册选取图片那一部分,发现始终出不来效果,所以搜索其他资料学习一下相关知识,写一个简单的demo。  一、 拍照选择图片...

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

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