package com.openrobot.common; import java.io.ByteArrayOutputStream; import java.io.IOException; import android.graphics.Rect; import android.graphics.YuvImage; import android.hardware.Camera; import android.hardware.Camera.Parameters; import android.hardware.Camera.PreviewCallback; import android.view.SurfaceHolder; import android.view.SurfaceHolder.Callback; import android.view.SurfaceView; /** * Source below is a modified a modified version of RobotEyes project by Charles L. Chen * */ public class CameraPreviewFeed implements Callback { private CameraPreviewFeedInterface delegate; private SurfaceHolder mHolder; private SurfaceView mPreview; private Camera mCamera; private boolean mTorchMode; private Rect r; private int previewHeight = 0; private int previewWidth = 0; private int previewFormat = 0; private byte[] mCallbackBuffer; private boolean busyProcessing = false; private ByteArrayOutputStream out; public CameraPreviewFeed(SurfaceView surfaceView, CameraPreviewFeedInterface delegate) { super(); mTorchMode = false; out = new ByteArrayOutputStream(); this.delegate = delegate; mPreview = surfaceView; mHolder = mPreview.getHolder(); mHolder.addCallback(this); mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { mHolder.setFixedSize(w, h); // Start the preview Parameters params = mCamera.getParameters(); previewHeight = params.getPreviewSize().height; previewWidth = params.getPreviewSize().width; previewFormat = params.getPreviewFormat(); // Crop the edges of the picture to reduce the image size r = new Rect(100, 100, previewWidth - 100, previewHeight - 100); mCallbackBuffer = new byte[460800]; mCamera.setParameters(params); mCamera.setPreviewCallbackWithBuffer(new PreviewCallback() { public void onPreviewFrame(byte[] imageData, Camera arg1) { if (!busyProcessing) { busyProcessing = true; processImage(imageData); } } }); mCamera.addCallbackBuffer(mCallbackBuffer); mCamera.startPreview(); setTorchMode(mTorchMode); } @Override public void surfaceCreated(SurfaceHolder holder) { mCamera = Camera.open(); try { mCamera.setPreviewDisplay(holder); } catch (IOException e) { e.printStackTrace(); } } @Override public void surfaceDestroyed(SurfaceHolder arg0) { if (mCamera != null) { mCamera.stopPreview(); mCamera.release(); mCamera = null; } } public void destroy() { this.surfaceDestroyed(null); delegate = null; } private void processImage(byte[] imageData) { if (this.delegate == null) { return; } try { YuvImage yuvImage = new YuvImage(imageData, previewFormat, previewWidth, previewHeight, null); yuvImage.compressToJpeg(r, 20, out); // Tweak the quality here - 20 seems pretty decent for quality + size. delegate.newImageFromCameraPreviewFeed(this, out.toByteArray()); } catch (IllegalStateException e) { e.printStackTrace(); } finally { out.reset(); if (mCamera != null) { mCamera.addCallbackBuffer(mCallbackBuffer); } busyProcessing = false; } } public void setTorchMode(boolean on) { if (mCamera != null) { Parameters params = mCamera.getParameters(); if (on) { params.setFlashMode(Parameters.FLASH_MODE_TORCH); } else { params.setFlashMode(Parameters.FLASH_MODE_AUTO); } mTorchMode = on; mCamera.setParameters(params); } } }