创新实训项目分析——第九篇

本文详细介绍了在Android环境下,如何实现相机应用的基本功能,包括拍照、预览页面设置和大图预览。通过分析代码,展示了如何使用Camera API进行拍照,处理照片数据并保存,以及在预览页面中设置按钮和显示照片。同时,讨论了在点击图片预览时的逻辑处理。最后,对项目后续的图片抗扭曲处理进行了展望。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2021SC@SDUSC


前言

以手机相机为依托的camera项目不仅需要有基础的拍照功能,并且还需要对拍摄的照⽚进⾏⼀系列处理,包括但不仅限于图⽚抗扭曲,曝光度,聚焦等。具体可以整理为以下功能:
1. 相机预览功能
2. 拍照的偏好设置,如闪光灯,聚焦,曝光补偿
3. 相机可随设备旋转,拍摄横屏和竖屏的照⽚
4. 拍照后保存在⼿机的pictures⽂件夹
5. 可以预览拍摄的照⽚
6. 图⽚抗扭曲处理
这篇将继续分析相机的预览。

一、项目环境

android studio版本 4.1.2

sdk版本 Compile SDK version:30

Build Tools Version 30.0.3

gradle版本 6.8.3

二、代码分析

1. 实现拍照

拍照主要用到的是Camera的takePicture()方法,通过指定回调函数,将照片数据写入到文件中。Camera API中,数据流主要是通过函数回调的方式,依照从下往上的方向,逐层 return 到 Applications 中。
引用https://blog.youkuaiyun.com/qq_16775897/article/details/77896218博主的流程图
在这里插入图片描述

调用mCamera.takePicture(),其第三个参数即指定回调函数Camera.PictureCallback().
当相机拍照完成后,就会触发onPictureTaken(),其中data参数就是jpeg格式的照片数据。我们需要调用getOutputMediaFile()获取输出文件,并向此文件写入照片数据。
getOutputMediaFile()方法会返回一个已经按照格式命名好的mediaFile文件,并且保存在了sd卡相应位置,赋值给pictureFile之后,pictureFile就是生成的照片文件。判断pictureFile正确生成,就调用FileOutputStream()方法,创建FileOutputStream流以写入数据到pictureFile对象表示的文件。首先使用File对象打开本地文件,从文件读取数据,使用FileOutputStream 类的write(byte[] b)方法,将转换的byte数组写入文件,写入完毕后一定要关闭数据流fos。
onPictureTaken()触发后相机会停止预览,我们在getOutputMediaFile()中能获取到media文件的路径outputMediaFileUri,在相应的照片的Imageview设置显示该media文件图像,并且此时我们手动添加camera.startPreview()让相机持续预览。

public void takePicture(final ImageView view) {
        mCamera.takePicture(null, null, new Camera.PictureCallback() {
            @Override
            public void onPictureTaken(byte[] data, Camera camera) {
                File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
                if (pictureFile == null) {
                    Log.d(TAG, "Error creating media file, check storage permissions");
                    return;
                }
                try {
                    FileOutputStream fos = new FileOutputStream(pictureFile);
                    fos.write(data);
                    fos.close();
                    view.setImageURI(outputMediaFileUri);
                    camera.startPreview();
                } catch (FileNotFoundException e) {
                    Log.d(TAG, "File not found: " + e.getMessage());
                } catch (IOException e) {
                    Log.d(TAG, "Error accessing file: " + e.getMessage());
                }
            }
        });
    }

效果如下在这里插入图片描述

2.预览页面设置

开发人员规划好的预览页面在activity_main.xml文件中设置
在这里插入图片描述
左下角的imageView保存刚刚拍下来的照片,拍照和设置两个button出发拍照和更改偏好设置两个事件。
之前开发人员没有对outputMediaFileType设置初始值,当还没有拍照时,点击imageView程序会闪退,此时outputMediaFileType中没有参数 mediaPreview.setOnClickListener()方法中接受不到getOutputMediaFileType()参数,无法进一步打开新的页面,所以会闪退,开发人员赋予outputMediaFileType初值为0,并且如果不等于image时,会出现提醒消息框,提醒用户要先进行拍照

Toast 是一个 View 视图,快速的为用户显示少量的信息。 Toast 在应用程序上浮动显示信息给用户,它永远不会获得焦点,不影响用户的输入等操作,主要用于给用户提供一些帮助提示。
Toast 最常见的创建方式是使用静态方法 Toast.makeText()

Toast toast=Toast.makeText(MainActivity.this,“先拍照才能预览哦”,Toast.LENGTH_LONG)
toast.setGravity(Gravity.TOP|Gravity.CENTER, -50, 100);
第一个参数:设置toast在屏幕中显示的位置。Gravity.TOP|Gravity.CENTER是居中靠顶
第二个参数:相对于第一个参数设置toast位置的横向X轴的偏移量,正数向右偏移,负数向左偏移
第三个参数:同的第二个参数


        mediaPreview.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                if(mPreview.getOutputMediaFileType().equals("image/*")){
                    Intent intent = new Intent(MainActivity.this, MainActivity2.class);

                    intent.setDataAndType(mPreview.getOutputMediaFileUri(), mPreview.getOutputMediaFileType());
                    startActivity(intent);
                }else {
                    Toast.makeText(MainActivity.this,"先拍照才能预览哦",Toast.LENGTH_LONG).show();

                }

            }
        });
    }

3.大图预览

点开左下角的imageView,刚刚拍下的照片会大图预览,为mediaView(即所说的imageView)添加响mediaPreview.setOnClickListener(new View.OnClickListener() {},点击时打开新的界面,即activity_main2所设计的页面一样,并且此时需要一个新的intent来传递参数,然后通过Data和Type向这个Intent传递拍到的照片URI,使得拍下来的照片可以在新的页面中间显示
界面预览:在这里插入图片描述

代码如下,intent从主程序MainActivity跳转到MainActivity2
MainActivity:


                if(mPreview.getOutputMediaFileType().equals("image/*")){
                    Intent intent = new Intent(MainActivity.this, MainActivity2.class);
                    intent.setDataAndType(mPreview.getOutputMediaFileUri(), mPreview.getOutputMediaFileType());
                    startActivity(intent);
             

MainActivity2:

public class MainActivity2 extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        Uri uri = getIntent().getData();
        FrameLayout preview = (FrameLayout) findViewById(R.id.preview);
        if (getIntent().getType().equals("image/*")) {
            ImageView view = new ImageView(this);
            view.setImageURI(uri);
            preview.addView(view);
        }
    }
}

三、总结

本次完成了相机预览设置的分析,下一篇将开始分析本项目的重点:图片抗扭曲处理,将扭曲的图片利用算法进行调整规划使之能够整齐地呈现在view中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值