package org.technocore.ui;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Random;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Bitmap.CompressFormat;
import android.hardware.CameraDevice;
import android.hardware.CameraDevice.CaptureParams;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.widget.ImageView;
public class PicuteCapturer extends Activity implements Runnable {
/**
* name of the file into which the image gets saved
*/
public static final String NAME_OF_IMAGE_FILE = "newPic.png";
public static final int PREVIEW_IMAGE_HEIGHT = 240;
public static final int PREVIEW_IMAGE_WIDTH = 320;
public static final int FULL_IMAGE_HEIGHT = 1024;
public static final int FULL_IMAGE_WIDTH = 1280;
/**
* Holds menu item names and ids
*/
enum MenuItems {
TAKE_PICTURE("Take Picture"), SAVE_PICTURE("Save picture"), RESUME_PREVIEW(
"Resume preview"), GO_BACK("Go back");
String menuItemText;
int id;
MenuItems(String menuItemText) {
this.menuItemText = menuItemText;
// create a unique id by using the name hash as a seed for the
// random
// number generator
id = (new Random(name().hashCode())).nextInt();
}
public String getMenuItemText() {
return menuItemText;
}
public int getId() {
return id;
}
}
/**
* boolean that stops the preview thread
*/
private boolean mTrucking = false;
/**
* time between calls to CameraDevice.capture during preview
*/
private long refreshRateInMilliSeconds = 1000;
/**
* counter for the image stamp
*/
private int counter = 1;
/**
* the main view that holds either a preview image or a final image
*/
private ImageView imageView;
/**
* This takes the pictures
*/
private CameraDevice cameraDevice;
/**
* handler for telling the ui thread that its time to update the preview
* picture
*/
private Handler handler;
/**
* since menu items get shown and hidden depending on the application state
* we need to keep a reference to the menu
*/
private Menu menu;
/**
* The imageview does not provide an easy way to get the bitmap out of it,
* so we hold on to it in case the user decides to save it
*/
private Bitmap bitmapToSave = null;
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
initBitMaps();
// initialise the handler and the view
handler = new Handler();
imageView = new ImageView(this);
setContentView(imageView);
}
final Runnable mUpdateResults = new Runnable() {
public void run() {
// this happens whenever its time to update the preview image
imageView.setImageBitmap(captureImage(true));
}
};
private Bitmap previewBitmap;
private Bitmap fullBitmap;
@Override
protected void onResume() {
super.onResume();
// once the application is resumed init the camera device and start the
// preview
cameraDevice = CameraDevice.open();
startPreview();
}
@Override
protected void onPause() {
super.onPause();
// close the camera device and stop the preview thread.
stopPreview();
cameraDevice.close();
}
private void startPreview() {
// only start one thread
if (!mTrucking) {
mTrucking = true;
Thread thread = new Thread(this);
thread.start();
}
}
private void stopPreview() {
// setting mTrucking to false ends the preview thread
mTrucking = false;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
boolean supRetVal = super.onCreateOptionsMenu(menu);
this.menu = menu;
menu.add(0, MenuItems.TAKE_PICTURE.getId(), MenuItems.TAKE_PICTURE
.getMenuItemText());
menu.add(0, MenuItems.SAVE_PICTURE.getId(), MenuItems.SAVE_PICTURE
.getMenuItemText());
menu.add(0, MenuItems.RESUME_PREVIEW.getId(), MenuItems.RESUME_PREVIEW
.getMenuItemText());
menu.add(0, MenuItems.GO_BACK.getId(), MenuItems.GO_BACK
.getMenuItemText());
// it doesn't make sense to let users save preview images or resume
// preview while previewing so hide those menu items
menu.setItemShown(MenuItems.SAVE_PICTURE.getId(), false);
menu.setItemShown(MenuItems.RESUME_PREVIEW.getId(), false);
return supRetVal;
}
@Override
public boolean onOptionsItemSelected(Menu.Item item) {
if (item.getId() == MenuItems.TAKE_PICTURE.getId()) {
// stop preview
stopPreview();
// take the big picture
bitmapToSave = captureImage(false);
// set it on the view
imageView.setImageBitmap(bitmapToSave);
// enable menu items
menu.setItemShown(MenuItems.SAVE_PICTURE.getId(), true);
menu.setItemShown(MenuItems.RESUME_PREVIEW.getId(), true);
return true;
} else if (item.getId() == MenuItems.SAVE_PICTURE.getId()) {
saveImage();
return true;
} else if (item.getId() == MenuItems.RESUME_PREVIEW.getId()) {
menu.setItemShown(MenuItems.SAVE_PICTURE.getId(), false);
menu.setItemShown(MenuItems.RESUME_PREVIEW.getId(), false);
startPreview();
return true;
} else if (item.getId() == MenuItems.GO_BACK.getId()) {
stopPreview();
finish();
return true;
}
return false;
}
private void saveImage() {
FileOutputStream fileOutputStream = null;
try {
// let everyone access the created image
fileOutputStream = this.openFileOutput(NAME_OF_IMAGE_FILE,
Context.MODE_WORLD_READABLE);
bitmapToSave.compress(CompressFormat.PNG, 100, fileOutputStream);
} catch (IOException e) {
showAlert("Failed!", "Couldn't save image " + NAME_OF_IMAGE_FILE,
"ok", false);
} finally {
try {
fileOutputStream.close();
} catch (IOException e) {
// do nothing
}
}
}
private void initBitMaps() {
previewBitmap = Bitmap.createBitmap(PREVIEW_IMAGE_WIDTH,
PREVIEW_IMAGE_HEIGHT, true);
fullBitmap = Bitmap.createBitmap(FULL_IMAGE_WIDTH, FULL_IMAGE_HEIGHT,
true);
}
private Bitmap captureImage(boolean preview) {
int width = -1;
int height = -1;
Canvas canvas = null;
Bitmap bitmapToUse = null;
CaptureParams cp = new CameraDevice.CaptureParams();
if (preview) {
width = PREVIEW_IMAGE_WIDTH;
height = PREVIEW_IMAGE_HEIGHT;
bitmapToUse = previewBitmap;
cp.type = 1;
} else {
width = FULL_IMAGE_WIDTH;
height = FULL_IMAGE_HEIGHT;
bitmapToUse = fullBitmap;
cp.type = 0;
}
cp.srcHeight = 1024;
cp.srcWidth = 1280;
cp.outputHeight = height;
cp.outputWidth = width;
cp.dataFormat = 2;
canvas = new Canvas(bitmapToUse);
// paint the canvas white, then use a black font
Paint paint = new Paint();
paint.setColor(Color.WHITE);
canvas.drawRect(new Rect(0, 0, width, height), paint);
if (cameraDevice != null) {
cameraDevice.setCaptureParams(cp);
if (cameraDevice.capture(canvas)) {
paint.setTextSize(25);
paint.setColor(Color.BLACK);
counter++;
// stamp the image so changes are apperent
canvas.drawText("MOOOO" + counter, 50, 50, paint);
}
}
return bitmapToUse;
}
@Override
public void run() {
while (mTrucking) {
// let the ui thread know its time to update the preview image
handler.post(mUpdateResults);
try {
Thread.sleep(refreshRateInMilliSeconds);
} catch (InterruptedException e) {
// do nothing
}
}
}
}