Android中获取图片那点事……

**Lroid是一款基于Anddroid平台开发的app, 是一款旨在提高刚想要入行Android系统开发(但已经具备Java语言基础)或者已经开始工作一段时间(但已经具备Java语言基础)想要进一步提高自己能力的app。lroid是以当下流行的MVP为架构,网络通信模块采用retrofit 2.0。里面还包括了RxJava,Dagger2等很热门的应用框架。为了更加接近现实常用的app,而不是一味的讲解Android开发知识点,本软件整合了一些内容来填充框架。
https://item.taobao.com/item.htm?id=541493148052**

在Android中图片可以说是我们开发必不可少的一样东东,关于图片的事真的太多太多了……,比如:图片的获取,图片的上传,图片的处理,如果处理不好就很有可能加载不出图片或者造成oom,我们的应用就直接over了,用户体验性很差很差。好,今天我给大家带来的是Android中如何获取图片,大家看一下如何获取图片,肯定哈哈大笑,图片获取谁不会啊,不就是加载一个链接(图片地址)么,这个有啥好说的。的确,直接加载一个链接确实能获取到图片,但那只是我们应用获取图片的一种途径,别忘了,我们的手机现在都可以拍照的哦~ 好,废话不多说,看看今天得主要内容。
  1. 开启照相机获取图片
  2. 自定义照相机获取图片
  3. 获取系统图库中的图片

强调内容本来想说一下常用的网络加载图片的框架,不过这个大家用的比较多,也比较熟练,我们就不做介绍了,相信大家用的已经很熟练了。

一、开启照相机获取图片。
在这里我要说一下,通过系统照相机获取图片有两种方式,一种是直接Intent照相机的ACTION,另一种就是自定义照相机,下面会有介绍。而第一种方式又分为两种,一个是获取图片的缩略图,另一种是获取原图。我们先来看一下简单的直接获取缩略图:

 Intent intentSystemSystemPath = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);         startActivityForResult(intentSystemSystemPath, 2);

没啥好说的……
再看一下onActivityResult方法:

 Bitmap bitmap3 = (Bitmap) data.getExtras().get("data");
iv_result.setImageBitmap(bitmap3);

通过Intent的get()方法,就可以获取到一个Bitmap对象,然后通过ImageView的setImageBitmap()方法就可以获取到了,这一种方法很简单,没啥好说的。看一下效果图:
这里写图片描述
这里获取的图片是一个缩略图,图片很小,可能有人就说了,我想获得一个高清的大图片该怎样呢,,,,,好,接下来就是通过第二种方式获取图片了,自定义一个路径,把照片保存到我们自定义的路径中。先来看代码:

    Intent intentSystemCustomPath = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                Date date = new Date();
                SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String fileName = format.format(date) + ".jpg";
                File fileFolder = new File(Environment.getExternalStorageDirectory() + "/lroid/");
                file = new File(fileFolder, fileName);
                if (!fileFolder.exists()){
                    fileFolder.mkdirs();
                }
                Uri uri = Uri.fromFile(file);
                intentSystemCustomPath.putExtra(MediaStore.EXTRA_OUTPUT,uri);
                startActivityForResult(intentSystemCustomPath,1);

这里要注意一下几点:

  1. 判断sd路径是否存在,我偷一下懒没有判断,希望大家养成一个好的编码习惯。
  2. File文件名的编写,
  3. intentSystemCustomPath.putExtra(MediaStore.EXTRA_OUTPUT,uri);这行代码,千万不要忘记了,否则我就获取不了图片了。这也是我们自定义路径的核心代码。

看一下解析:

FileInputStream fileInputStream = null;
                    try {
                        fileInputStream = new FileInputStream(file);
                        BitmapFactory.Options options = new BitmapFactory.Options();
                        options.inSampleSize = 4;
                        Bitmap bitmap2 = BitmapFactory.decodeStream(fileInputStream,null,options);
                        iv_result.setImageBitmap(bitmap2);
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    }finally {
                        if(fileInputStream!=null){
                            try {
                                fileInputStream.close();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }

这里要注意的事,BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4;
代码的意思,我们知道现在手机像素很高,要是我们一下子加载很大的文件到内存,很容易造成oom,而且ImageView也显示不了(已经测试了),所以要进行压缩一下,这样ImageView就能显示了,效果图如下:这里写图片描述
是不是明显比上面图片 获取到的图片大很多呢。。。。嘿嘿,其实还是挺简单的。打开手机sd卡,找到图片目录就会发现,我们刚才拍摄的照片已经生成了,这里就不再展示效果图了,大家一定要亲手做一下。

二、自定义照相机
自定义相机,我们就不能再通过Intent来打开照相机了,我们得通过摄像头自己写一个相机了,好,来看一下布局文件:

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


    <SurfaceView
        android:id="@+id/id_sv_image_display"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="拍照"
        android:id="@+id/id_bt_image_take_capture"
        android:layout_gravity="bottom" />

</FrameLayout>

还是很简单的,SurfaceView,大家可能在平常开发中用的比较少,可能有点陌生,没事,大家就把它当一个实时改变图片的ImageView用就行,它内部维护了一个Canvas,而且不是在主线程更新图像,可以实时把摄像头捕获的图像信息展示出来。它的内部实现比较复杂,我们以后有时间再进行介绍。
再来看一下代码:

/**
 * Created by LiuFeng on 2016-02-25.
 * 邮箱:596484713@qq.com
 */
public class CameraFragment extends BaseFragment {

    private Camera mCamera;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_image_camera_layout,container,false);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        Button bt_take_capture = (Button) view.findViewById(R.id.id_bt_image_take_capture);
        bt_take_capture.setOnClickListener(this);

        SurfaceView mSurfaceView = (SurfaceView) view.findViewById(R.id.id_sv_image_display);
        SurfaceHolder surfaceHolder = mSurfaceView.getHolder();
        surfaceHolder.setKeepScreenOn(true);
        surfaceHolder.addCallback(new MyCallBack());
    }

    @Override
    public void onClick(View v) {
        super.onClick(v);
        switch (v.getId()){
            case R.id.id_bt_image_take_capture:
                mCamera.autoFocus(null);
                mCamera.takePicture(null, null, new Camera.PictureCallback() {
                    @Override
                    public void onPictureTaken(byte[] data, Camera camera) {
                        try {
                            FileOutputStream outputStream = new FileOutputStream(MethodUtils.getImageFile());
                            outputStream.write(data);
                            outputStream.close();
                            Intent intent = new Intent();
                            Bundle bundle = new Bundle();
                            bundle.putByteArray("data",data);
                            intent.putExtras(bundle);
                            ((Activity) mContext).setResult(Activity.RESULT_OK, intent);
                            ((Activity) mContext).finish();

                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                });
                break;
        }
    }


    class MyCallBack implements SurfaceHolder.Callback {

        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            mCamera = Camera.open();
            try {
                mCamera.setPreviewDisplay(holder);
                mCamera.startPreview();
                mCamera.autoFocus(null);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            Camera.Parameters parameters = mCamera.getParameters();
            parameters.setPictureFormat(ImageFormat.JPEG);
            parameters.setPreviewSize(width, height);
            parameters.setPreviewFpsRange(5, 10);
            parameters.setPictureSize(width, height);
            parameters.setJpegQuality(80);
            mCamera.setParameters(parameters);
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            if (mCamera!=null){
                mCamera.release();
                mCamera = null;
            }
        }
    }

}

这里我用的是Fragment,其实和Activity一样的。不要纠结这个~
这个代码也没啥好讲的,在看的时候,想想以下几个问题:

  1. 如何获取系统的摄像头
  2. 如何把SurfaceView和摄像头捕捉的画面联系起来
  3. 如何进行拍照
  4. 如何释放摄像头资源,因为摄像头是系统共享资源,一定要释放,否则会造成系统照相机不能用。

相信把这几个问题想明白了,上面的代码还是很简单的。我个人比较喜欢启发式学习,这样印象才深刻。看一个比较关键的地方:

Intent intent = new Intent();
                            Bundle bundle = new Bundle();
                            bundle.putByteArray("data",data);
                            intent.putExtras(bundle);
                            ((Activity) mContext).setResult(Activity.RESULT_OK, intent);
                            ((Activity) mContext).finish();

这几行代码的意思就是把获取到的照片信息返回到请求的Activity,和系统的类似,其实系统照相机也是采取这样的方式来把图片信息返回给我们。来看一下效果图:
这里写图片描述
这里写图片描述
可以看到图片还是很好的。

三、获取系统图库中的图片
第三中获取图片的方式和第一种有点类似,也是通过Intent,而且只能通过Intent获取。好了直接上代码:

Intent intentSystemGallery = new Intent(Intent.ACTION_GET_CONTENT);
                intentSystemGallery.setType("image/*");
                startActivityForResult(intentSystemGallery,3);
 Uri uri =  data.getData();
                    BitmapFactory.Options options = new BitmapFactory.Options();
                    options.inSampleSize = 4;
                    Bitmap bitmap4 = BitmapFactory.decodeFile(uri.getPath(),options);
                    iv_result.setImageBitmap(bitmap4);

和通过摄像头获取的方式基本类似,这里就不过多介绍了。

好了,以上就是今天得主要内容,平时用的比较的多的,比如上传个头像啊,发表个动态什么的,用处还是很广泛的,大家有什么疑问,欢迎进群:439175602 我们一起讨论。Thx

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值