How can I modify live camera view on Android?
I was searching and found this app https://play.google.com/store/apps/details?id=com.fingersoft.cartooncamera as good example what I want to do. I wanted to apply some effect to my camera view as well. I need to find a way to add some effects or draw something on my camera view.
As far as I understood I have to get some video stream, apply some changes and show back in camera view.
Any ideas?
Much thanks!
You can find more information about this topic Android - Camera Preview and in this post.
A completely other approach would be to use OpenCV.
The smallest piece of code I could think of to get an image and preview it on the screen looks like this:
public class MainActivity extends Activity implements Callback {
Camera camera;
SurfaceView surfaceView;
SurfaceHolder holder;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
surfaceView = (SurfaceView) findViewById(R.id.surfaceView1);
}
#Override
protected void onResume() {
super.onResume();
camera = Camera.open();
Camera.Parameters parameters = camera.getParameters();
parameters.setPictureFormat(ImageFormat.JPEG);
camera.setParameters(parameters);
holder = surfaceView.getHolder();
holder.addCallback(this);
camera.setPreviewCallback(new PreviewCallback() {
public void onPreviewFrame(byte[] data, Camera camera) {
// You could apply some pixel operations directly here.
Log.d("Camera", "Camera image aquired");
}
});
}
#Override
protected void onPause() {
super.onPause();
camera.stopPreview();
camera.release();
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
try {
camera.setPreviewDisplay(holder);
} catch (IOException e) {
e.printStackTrace();
}
camera.startPreview();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
}
A full example that does this, can be found on GitHub.
Related
When my application is opened and I press power Button and reopen the Tablet, the Camera hangs. I have tried setting the SurfaceView Camera on onResume() method again, but was not able to solve the problem and have tried to start (camera1.startpreview()) but still I am facing the same problem.
My Surface View's camera code is:
SurfaceView cameraPreview1;
SurfaceHolder previewHolder1;
public static Camera camera2;
boolean inPreview;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
inPreview = false;
cameraPreview1 = (SurfaceView)findViewById(R.id.cameraPreview1);
previewHolder1 = cameraPreview1.getHolder();
previewHolder1.addCallback(surfaceCallback);
previewHolder1.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
public void onResume() {
super.onResume();
camera2=Camera.open(1);
mPicture1 = getPictureCallback();
}
#Override
public void onPause() {
super.onPause();
//when on Pause, release camera in order to be used from other applications
releaseCamera();
}
private void releaseCamera() {
// stop and release camera
if (camera2 != null) {
camera2.release();
camera2 = null;
}
}
SurfaceHolder.Callback surfaceCallback=new SurfaceHolder.Callback() {
public void surfaceCreated(SurfaceHolder holder) {
try {
camera2.setPreviewDisplay(previewHolder1);
}
catch (Throwable t) {
Log.e(TAG, "Exception in setPreviewDisplay()", t);
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Camera.Parameters parameters=camera2.getParameters();
Camera.Size size=getBestPreviewSize(width, height, parameters);
if (size!=null) {
parameters.setPreviewSize(size.width, size.height);
camera2.setParameters(parameters);
camera2.startPreview();
inPreview=true;
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// not used
}
You're calling setPreviewDisplay() in surfaceCreated(), but the surface isn't necessarily destroyed and recreated when you turn the screen off and back on with the power button (see notes here). I don't think the Camera is hung, I think it just isn't sending the preview frames to the Surface, because surfaceCreated() isn't being called a second time.
The way to fix this is to detect if the Surface has already been created, by setting a static variable in surfaceCreated() and clearing it in surfaceDestroyed(). If the Surface is already set up when you enter onResume(), you need to call setPreviewDisplay() on the new Camera object.
Grafika's "texture from camera" activity demonstrates tracking the Surface with a static variable. FWIW, Grafika's "continuous capture" activity gets this wrong as well.
I come to you because my custom camera has a big problem : the image is stretched! I have rade that the problem from dimensions but i don't solved it.
If you want pictures to show the problem I will post it
This is my code :
public class CameraActivity extends Activity{
private SurfaceView surface_view;
private Camera mCamera;
SurfaceHolder.Callback sh_ob = null;
SurfaceHolder surface_holder = null;
SurfaceHolder.Callback sh_callback = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFormat(PixelFormat.TRANSLUCENT);
surface_view = new SurfaceView(getApplicationContext());
addContentView(surface_view, new WindowManager.LayoutParams(WindowManager.LayoutParams.FILL_PARENT, WindowManager.LayoutParams.FILL_PARENT));
if (surface_holder == null) {
surface_holder = surface_view.getHolder();
}
sh_callback = my_callback();
surface_holder.addCallback(sh_callback);
}
SurfaceHolder.Callback my_callback() {
SurfaceHolder.Callback ob1 = new SurfaceHolder.Callback() {
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
mCamera = Camera.open();
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException exception) {
mCamera.release();
mCamera = null;
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
mCamera.startPreview();
}
};
return ob1;
}
}
Thanks for your help :D
You cannot stretch the surface on full screen; you should set it according to camera aspect ratio. To cover all situations, you need more callbacks. See a nice wrapper class here: http://www.vogella.com/code/de.vogella.android.gallery/src/com/example/android/hcgallery/CameraFragment.html
public class PhotoActivity extends Activity implements SurfaceHolder.Callback {
private ImageView imageView;
private SurfaceView mSurfaceView;
private Bitmap bmp;
private SurfaceHolder mSurfaceHolder;
private Camera mCamera;
private Parameters parameters;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSurfaceView = (SurfaceView) findViewById(R.id.surface_camera);
imageView = (ImageView) findViewById(R.id.image_view);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
parameters = mCamera.getParameters();
mCamera.setParameters(parameters);
mCamera.startPreview();
Camera.PictureCallback mCall = new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
bmp = BitmapFactory.decodeByteArray(data, 0, data.length);
imageView.setImageBitmap(bmp);
mSurfaceView.setVisibility(View.INVISIBLE);
// Call web service
SendPhotoAsync photoToWeb = new SendPhotoAsync(data);
photoToWeb.execute();
}
};
mCamera.takePicture(null, null, mCall);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
mCamera = Camera.open();
mCamera.setDisplayOrientation(90);
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException exception) {
mCamera.release();
mCamera = null;
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
#Override
protected void onResume() {
super.onResume();
}
#Override
protected void onPause() {
super.onPause();
}
how i could modify this code to detect face on camera preview,using face detector api in android.. any help please..
i also want to detect eyes then..hope someone can help me..i went through thiswhich works on button click.in my case for taking photo no button click is there..
someone with some productive code will be appreciable..please help me its very critical
if you have the android API for face detector..call this activity from the photo activity..in photo activity save the captured image to sd card...read this file in the face detector api..thus we can make it..but samsung galaxy+google nexus doesnt perform face detection..AAkash does..
I got two strange problems:
1-i'm using previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); in an App and it works normally and I tried to use the same method in another App, I found eclipse cross this method with a black line and says this method is deprecated while I'm using the same method in another App and it works correctly without any problems
JAVA CODE:
public class AugReal00 extends Activity {
SurfaceView cameraPreview;
SurfaceHolder previewHolder;
Camera camera;
Boolean inPreview;
SurfaceHolder.Callback surfaceCallback = new Callback() {
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
camera.stopPreview();
camera.release();
camera = null;
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
try {
//Open The Camera
this.camera = android.hardware.Camera.open();
this.camera.setPreviewDisplay(this.holder);
}
catch(IOException ioe) {
ioe.printStackTrace(System.out);
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
android.hardware.Camera.Parameters parameters = camera.getParameters();
parameters.setSceneMode(parameters.SCENE_MODE_SPORTS);
parameters.setFlashMode(parameters.FLASH_MODE_ON);
parameters.setPreviewSize(width/2, height/2);
parameters.setPictureSize(width/2, height/2);
camera.setParameters(parameters);
camera.startPreview();
}
};// end of surfaceCallback Listener
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_aug_real00);
inPreview = false;
cameraPreview = (SurfaceView) findViewById(R.id.cameraPreview);
previewHolder = cameraPreview.getHolder();
previewHolder.addCallback(surfaceCallback);
previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
//previewHolder.se;
}
public void OnResume() {
super.onResume();
camera = Camera.open();
}// end of OnResume
public void OnPause() {
if (inPreview) {
camera.stopPreview();
}
camera.release();
camera=null;
inPreview=false;
super.onPause();
}// end of OnPause.
2-I wrote a simple program and i found that eclipse gives me the following error
syntax error, insert } to complete class body
while all the brackets are closed and every thing should work fine. I don't know how to solve this issue.
Check your old app sdk version number. The same api can be deprecated in next versions.
You have not closed an opened brace. Make sure all the braces are properly inserted.
I'm trying to make a screen where the use will be able to take a photo. This photo will go to the database. The problem is, I've tried multiple approaches and in every approach, I need to use the PictureCallback. But the onPictureMethod from PictureCallback is never called, no matter what.
I already tried looking into this and this, but still can't move.
Edit: Using Android 2.2 (API 8)
EDITED CODE:
package touchcare.idealogix.android;
//imports
public class CameraActivityTest extends Activity implements SurfaceHolder.Callback
{
private SurfaceView surfaceCamera;
private SurfaceHolder holderCamera;
private Camera camera;
private Button btnCapture;
private PictureCallback mPictureJpg;
private PictureCallback mPictureRaw;
private ShutterCallback shutterCallback;
#Override public void onCreate(Bundle bundle){
super.onCreate(bundle);
setContentView(R.layout.layout_camera);
Log.d("PICTURE", "ACTIVITY START");
surfaceCamera = (SurfaceView) findViewById(R.id.surfaceCamera);
btnCapture = (Button) findViewById(R.id.btnCapture);
holderCamera = surfaceCamera.getHolder();
holderCamera.addCallback(this);
holderCamera.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
shutterCallback = new ShutterCallback()
{
#Override
public void onShutter()
{
//DONOTHING
}
};
mPictureRaw = new PictureCallback()
{
#Override
public void onPictureTaken(byte[] data, Camera camera)
{
//DONOTHING
}
};
mPictureJpg = new PictureCallback()
{
#Override
public void onPictureTaken(byte[] data, Camera camera)
{
Log.d("PICTURE", "ON PICTURE TAKEN START");
Intent intent = getIntent();
final boolean beds = intent.getExtras().getBoolean(Main.BEDS, false);
final boolean nurse = intent.getExtras().getBoolean(Main.NURSE, false);
final int position = intent.getExtras().getInt(Main.POSITION, 0);
if(beds)
{
BedroomDataSource bedDs = new BedroomDataSource(CameraActivityTest.this);
String where = SQLiteBedroomHelper.COLUMN_UID + "=" + AppData.getBedrooms().get(position).getUid();
bedDs.open();
bedDs.updateBedroom(where, null, null, null, null, null, null, data);
bedDs.close();
Log.d("PICTURE", "BEDS BOOLEAN");
AppData.getBedrooms().get(position).setImage(data);
}else if(nurse)
{
}
Log.d("PICTURE", "ON PICTURE TAKEN END");
finish();
}
};
btnCapture.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View arg0)
{
camera.takePicture(shutterCallback, mPictureRaw, mPictureJpg);
}
});
}
#Override public void surfaceCreated(SurfaceHolder holder)
{
camera = Camera.open();
Camera.Parameters params = camera.getParameters();
params.setPreviewSize(holder.getSurfaceFrame().width(), holder.getSurfaceFrame().height());
params.setPictureSize(32, 32);
params.setJpegQuality(100);
camera.setParameters(params);
try
{
camera.setPreviewDisplay(holder);
}catch(IOException ex){
Log.d("PICTURE", "PREVIEW EXCEPTION");
}
camera.startPreview();
Log.d("PICTURE", "SURFACE CREATED");
}
#Override public void surfaceChanged(SurfaceHolder holder, int format, int w, int h)
{
Log.d("PICTURE", "SURFACE CHANGED");
}
#Override public void surfaceDestroyed(SurfaceHolder holder)
{
camera.stopPreview();
camera.release();
Log.d("PICTURE", "SURFACE DESTROYED");
}
}
Thanks.
EDIT: Looks like that some photos are taken and the callback is reached. The database gets the photos, and loads back in bitmap just fine. But depending on what I'm taking a photo of, the callback isn't reaching. Smaller and simpler things are 100% chance the callback will be executed.
It looks like you create the callback mPicture, and then never set it as the callback for anything. I've never used any picture stuff, so I can't advise on where to set it, but as far as I know you need to register the callback for it to be called, just defining it won't do you any good.