May 6, 2008

(Android) How to use the CameraDevice class

After several researches of CameraDevice class, i found a good exemple to show how it works. I added a start button to launch the camera, press the middle button to save an image, the image is saved in /data/data/name of package/files/. Press the back button to continue take pictures.


package cameratest;

import java.io.FileOutputStream;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.PixelFormat;
import android.graphics.Bitmap.CompressFormat;
import android.hardware.CameraDevice;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;

public class CameraTest extends Activity{
private Preview mPreview;
private int i = 0;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);

// Make sure to create a TRANSLUCENT window. This is recquired
// for SurfaceView to work. Eventually this'll be done by
// the system automatically.
getWindow().setFormat(PixelFormat.TRANSLUCENT);
mPreview = new Preview(this);

LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);

Button bt = new Button(this);
bt.setText("start");
bt.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View arg0) {
setContentView(mPreview);
}
});

layout.addView(bt, new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
setContentView(layout);
}

@Override
protected boolean isFullscreenOpaque() {
// Our main window is set to translucent, but we know that we will
// fill it with opaque data. Tell the system that so it can perform
// some important optimizations.
return true;
}

@Override
protected void onResume()
{
// Because the CameraDevice object is not a shared resource,
// it's very important to release it when the activity is paused.
super.onResume();
mPreview.resume();
}

@Override
protected void onPause()
{
// Start Preview again when we resume.
super.onPause();
mPreview.pause();
}

@Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER)
{
mPreview.pause();
takePicture();
Log.i("info", "center key pressed cameratest");
return true;
}
else if (keyCode == KeyEvent.KEYCODE_BACK)
{
mPreview.resume();
Log.i("info", "back key pressed cameratest");
return true;
}
return false;
}

public void takePicture(){
CameraDevice camera = CameraDevice.open();
if (camera != null) {
Log.i("MyLog", "inside the camera");
CameraDevice.CaptureParams param = new CameraDevice.CaptureParams();
param.type = 1; // preview
param.srcWidth = 1280;
param.srcHeight = 960;
param.leftPixel = 0;
param.topPixel = 0;
param.outputWidth = 320;
param.outputHeight = 240;
param.dataFormat = 2; // RGB_565
camera.setCaptureParams(param);

Bitmap myPic = Bitmap.createBitmap(320, 240, false);
Canvas canvas = new Canvas(myPic);
try {
FileOutputStream stream = this.openFileOutput("picture" + i++ + ".png", 1);
camera.capture(canvas);
myPic.compress(CompressFormat.PNG, 100, stream);
stream.flush();
stream.close();
Log.i("info", "create a picture");
}catch(Exception e) { Log.i("info", "exception "+e.toString()); }

// Make sure to release the CameraDevice
if (camera != null)
camera.close();
}
}
}

class Preview extends SurfaceView implements SurfaceHolder.Callback {
SurfaceHolder mHolder;
private PreviewThread mPreviewThread;
private boolean mHasSurface;

Preview(Context context) {
super(context);

// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
mHasSurface = false;

// In this example, we hardcode the size of the preview. In a real
// application this should be more dynamic. This guarantees that
// the uderlying surface will never change size.
mHolder.setFixedSize(320, 240);
}

public void resume() {
// We do the actual acquisition in a separate thread. Create it now.
if (mPreviewThread == null) {
mPreviewThread = new PreviewThread();
// If we already have a surface, just start the thread now too.
if (mHasSurface == true) {
mPreviewThread.start();
}
}
}

public void pause() {
// Stop Preview.
if (mPreviewThread != null) {
mPreviewThread.requestExitAndWait();
mPreviewThread = null;
}
}

public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, start our main acquisition thread.
mHasSurface = true;
if (mPreviewThread != null) {
mPreviewThread.start();
}
}

public void surfaceDestroyed(SurfaceHolder holder) {
// Surface will be destroyed when we return. Stop the preview.
mHasSurface = false;
pause();
}

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// Surface size or format has changed. This should not happen in this
// example.
}


class PreviewThread extends Thread {
private boolean mDone;

PreviewThread() {
super();
mDone = false;
}

@Override
public void run() {
// We first open the CameraDevice and configure it.
CameraDevice camera = CameraDevice.open();
if (camera != null) {
CameraDevice.CaptureParams param = new CameraDevice.CaptureParams();
param.type = 1; // preview
param.srcWidth = 1280;
param.srcHeight = 960;
param.leftPixel = 0;
param.topPixel = 0;
param.outputWidth = 320;
param.outputHeight = 240;
param.dataFormat = 2; // RGB_565
camera.setCaptureParams(param);
}

// This is our main acquisition thread's loop, we go until
// asked to quit.
SurfaceHolder holder = mHolder;
while (!mDone) {
// Lock the surface, this returns a Canvas that can
// be used to render into.
Canvas canvas = holder.lockCanvas();

// Capture directly into the Surface
if (camera != null) {
camera.capture(canvas);
}

// And finally unlock and post the surface.
holder.unlockCanvasAndPost(canvas);
}

// Make sure to release the CameraDevice
if (camera != null)
camera.close();
}

public void requestExitAndWait() {
// don't call this from PreviewThread thread or it a guaranteed
// deadlock!
mDone = true;
try {
join();
} catch (InterruptedException ex) { }
}
}
}

No comments: