14.3.2 实现自己的拍照Activity(2)

14.3.2  实现自己的拍照Activity(2)

在编写Preview类时应注意如下7点:

由于Preview是CameraPreview的内嵌类(CameraPreview就是自定义的拍照Activity)。因此,在Preview类中通过putExtra方法保存的数据会在调用CameraPreview的类中通过onActivityResult事件方法获得。

Camera类的takePicture方法有3个参数,都是回调对象,但比较常用的是最后一个参数。当拍完照后会调用该参数指定对象中的onPictureTaken方法,一般可以在该方法中对照片数据做进一步处理。例如,在本例中使用putExtra方法以key-value对保存了照片数据。

当手机摄像头的状态变化时,例如手机由纵向变成横向,或分辨率发生变化后,很多参数需要重新设置,这时系统就会调用SurfaceHolder.Callback 接口的surfaceChanged方法。因此,可以在该方法中对摄像头的参数进行设置,包括调用startPreview方法进行拍照。

根据手机的拍摄方向(纵向或横向),需要设置预览尺寸。surfaceChanged方法的最后两个参数表示摄像头预览时的实际尺寸。在使用Camera.Parameters类的setPreviewSize方法设置预览尺寸时,如果是纵向拍摄,setPreviewSize方法的第1个参数值是h,第2个参数值是w,如果是横向拍摄,第1个参数值是w,第2个参数值是h。在设置时千万不要弄错了,否则当手机改变拍摄方向时无法正常拍照。读者可以改变Preview类中的预览尺寸,看看会产生什么效果。

如果想设置照片的实际分辨率,需要使用Camera.Parameters类的setPictureSize方法进行设置。

本例中通过在CameraActivity中添加ImageView的方式在预览界面显示了一个表示对焦状态的图像。这个图像文件有两个:focus1.png和focus2.png。其中focus1.png是白色的透明图像,表示正在对焦。focus2.png是绿色的透明图像,表示对焦成功。在开始拍照后,先显示focus1.png,当对焦成功后,系统会调用AutoFocusCallback接口的onAutoFocus方法。在该方法中将ImageView中显示的图像变成focus2.png,表示对焦成功,这时就可以结束拍照了。

在拍完照后需要调用Camera类的release方法释放手机摄像头,否则除非重启手机,否则其他的应用程序无法再使用摄像头进行拍照。

本例通过触摸拍照预览界面结束拍照。因此,需要使用Activity的onTouchEvent事件方法来处理屏幕触摸事件,代码如下:

public boolean onTouchEvent(MotionEvent event)  
{  
    if (event.getAction() == MotionEvent.ACTION_DOWN)  
        //  结束拍照  
        preview.takePicture();  
    return super.onTouchEvent(event);  

其中preview是Preview类的对象实例,在CameraPreview类的onCreate方法中创建了该对象。

在编写完CameraPreview类后,可以在其他的类中使用如下代码启动CameraPreview,启动CameraPreview后会自动进行拍照:

Intent intent = new Intent(this, CameraPreview.class);  
startActivityForResult(intent, 1); 

在关闭CameraPreview后(可能是拍照成功,也可能是取消拍照),可以通过onActivityResult方法来获得成功拍照后的照片数据,代码如下:

protected void onActivityResult(int requestCode, int resultCode, Intent data)  
{  
    if (requestCode == 1)  
    {  
        //  拍照成功后,响应码是20  
        if (resultCode == 20)  
        {  
            Bitmap cameraBitmap;  
            //  获得照片数据(byte数组形式)  
            byte[] bytes = data.getExtras().getByteArray("bytes");  
            //  byte数组转换成Bitmap对象  
            cameraBitmap = BitmapFactory.
decodeByteArray(bytes, 0,bytes.length);  
            //  根据拍摄的方向旋转图像(纵向拍摄时需要将图像旋转90度)  
            if (getWindowManager().getDefaultDisplay
().getOrientation() == 0)  
            {  
                Matrix matrix = new Matrix();  
                matrix.setRotate(90);  
                cameraBitmap = Bitmap.createBitmap(cameraBitmap, 0, 0,  
                        cameraBitmap.getWidth(), 
cameraBitmap.getHeight(),matrix, true);  
            }  
            //  将照片保存在SD卡的根目录(文件名是camera.jpg  
            File myCaptureFile = new File("/sdcard/camera.jpg");  
            try  
            {  
                BufferedOutputStream bos = new BufferedOutputStream(  
                        new FileOutputStream(myCaptureFile));  
                cameraBitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);  
                bos.flush();  
                bos.close();  
                imageView.setImageBitmap(cameraBitmap);  
            }  
            catch (Exception e)  
            {  
            }  
       }  
    }  
    super.onActivityResult(requestCode, resultCode, data);  

在编写上面代码时应注意如下两点:

由于纵向拍摄时生成的照片是横向的,因此需要在处理照片时将其顺时针旋转90度。在14.3.1节介绍的系统拍照Activity已经将照片处理完了,因此,不需要对照片进行旋转。

由于直接使用Camera类进行拍照时,系统不会自动保存照片,因此,就需要在处理照片时自行确定照片的存储位置,并保存照片。这种方法的优点是灵活,缺点是需要写更多的代码。至于是选择系统提供的拍照功能,还是选择自己实现拍照功能,可根据具体的情况而定。如果对照片保存的位置没什么要求,而且对照片的分辨率要求不高。可以使用系统提供的拍照功能,否则,就要自己来实现拍照功能了。

虽然到现在为止拍照的功能已经完全实现了,但程序在手机或模拟器上仍然不能正常运行,原因是需要在AndroidManifest.xml文件中设置拍照的权限许可(在调用系统提供的拍照功能时并不需要设置拍照权限许可),代码如下:

<uses-permission android:name="android.permission.CAMERA" /> 

本例的运行效果与14.3.1节的例子的运行效果类似,只是在拍照时需要触摸屏幕才能结束拍照。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值