Android 系列 5.6使用android.media.Camera拍照

本文介绍如何通过自定义SurfaceView和实现Camera对象的控制回调来创建一个具有高级拍照功能的Android应用。用户可以精确控制拍照过程,并能访问和修改原始图像数据。

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

5.6使用android.media.Camera拍照
问题
您想要在拍摄照片时对所涉及的各个阶段有更多的控制。

创建SurfaceView并实现当用户拍摄照片时触发的回调,以便控制图像捕获进程。
讨论
有时,您可能希望在拍摄照片时对所涉及的阶段进行更多的控制,或者您可能想要访问和修改相机获取的原始图像数据。在这些情况下,使用简单的Intent来拍照是不够的。
我们将创建一个新的Activity并自定义视图,使其在onCreate方法中全屏显示(示例5-11)。
实施例5-11。拍照活动
Preview类是配方的主体。它处理绘制像素的Surface和Camera对象。
我们在构造函数中定义一个ClickListener,以便用户可以通过在屏幕上点击一次来拍摄照片。一旦我们收到点击的通知,我们拍摄一张图片,作为参数传递四(所有可选)回调(参见示例5-12)。
实例5-12。 SurfaceView实现
class Preview extends SurfaceView implements SurfaceHolder.Callback, PictureCallback {
private SurfaceHolder mHolder;
private Camera mCamera;
private RawCallback mRawCallback;
public Preview(Context context) {
super(context);
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mRawCallback = new RawCallback();
setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mCamera.takePicture(mRawCallback, mRawCallback, null,
Preview.this);
}
});
}


Preview类实现了SurfaceHolder.Callback接口,以便在创建,更改和销毁基础表面时获得通知。我们将使用这些回调来正确处理Camera对象(参见示例5-13)。
实例5-13。 surfaceChanged()方法
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(width, height);
mCamera.setParameters(parameters);
mCamera.startPreview();
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
mCamera = Camera.open();
configure(mCamera);
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException exception) {
closeCamera();
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
closeCamera();
}



一旦相机被创建,我们调用配置为了设置相机将使用拍摄图片的参数 - 例如闪光模式,效果,图片格式,图片大小,场景模式等(例5-14)。由于并非所有设备都支持各种功能,因此在设置前,请先询问支持哪些功能。
实例5-14。 configure()方法
private void configure(Camera camera) {
Camera.Parameters params = camera.getParameters();
// Configure image format. RGB_565 is the most common format.
List<Integer> formats = params.getSupportedPictureFormats();
if (formats.contains(PixelFormat.RGB_565))
params.setPictureFormat(PixelFormat.RGB_565);
else
params.setPictureFormat(PixelFormat.JPEG);
// Choose the biggest picture size supported by the hardware
List<Size> sizes = params.getSupportedPictureSizes();
Camera.Size size = sizes.get(sizes.size()-1);
params.setPictureSize(size.width, size.height);
List<String> flashModes = params.getSupportedFlashModes();
if (flashModes.size() > 0)
params.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
// Action mode takes pictures of fast moving objects
List<String> sceneModes = params.getSupportedSceneModes();
if (sceneModes.contains(Camera.Parameters.SCENE_MODE_ACTION))
params.setSceneMode(Camera.Parameters.SCENE_MODE_ACTION);
else
params.setSceneMode(Camera.Parameters.SCENE_MODE_AUTO);
// if you choose FOCUS_MODE_AUTO remember to call autoFocus() on
// the Camera object before taking a picture
params.setFocusMode(Camera.Parameters.FOCUS_MODE_FIXED);
camera.setParameters(params);
}

当表面被破坏,我们关闭相机,释放其资源:
private void closeCamera() {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
}

jpeg回调是最后一个调用;这是我们重新启动预览并将文件保存在磁盘上的位置。
@Override
public void onPictureTaken(byte[] jpeg, Camera camera) {
// now that all the callbacks have been called it is safe to resume preview
mCamera.startPreview();
saveFile(jpeg);
}
}


最后,我们实现ShutterCallback,我们再次实现
PictureCallback接收未压缩的原始图像数据(参见示例5-15)。

实例5-15。 ShutterCallback实现

class RawCallback implements ShutterCallback, PictureCallback {
@Override
public void onShutter() {
// notify the user, normally with a sound, that the picture has
// been taken
}
@Override
public void onPictureTaken(byte[] data, Camera camera) {
// manipulate uncompressed image data
}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值