13

I am working on an app for android that uses the front facing camera to simulate a mirror for the user. I need the app to take a picture every 5 seconds as a bitmap(automatically and without user interaction), which I then combine with another bitmap later on.

The difficult part for me: How to take a picture and get it as a bitmap?

I tried several solutions, but none have worked yet.

The other question that this is marked as a duplicate for is for doing this manually and not automatically.

StephenA
  • 61
  • 6
moobi
  • 7,849
  • 2
  • 18
  • 29
  • 1
    have you seen [this](http://developer.android.com/training/camera/photobasics.html).If you had and still have a problem why don't you try posting some of your code – magmike May 28 '14 at 20:30
  • check my answer for full code – mremremre1 May 28 '14 at 21:05
  • 1
    @tyczj, your proposed link opens the camera and the user has to take a picture himself. I tried something like that. I cant use it, because I like my app to take pictures automatically and inside my app! – moobi May 28 '14 at 23:40
  • Nominated for reopening. This asks for a method without user interaction, while the other requires user interaction. – Ciro Santilli OurBigBook.com Feb 15 '16 at 18:37
  • One thing that did work is to decode the jpeg byte array from `camera.takePicture` with `BitmapFactory.decodeByteArray`. Likely a silly approach that encodes / decodes twice :-) – Ciro Santilli OurBigBook.com Feb 15 '16 at 18:55
  • Other formats may not be available with `camera.takePicture`: http://stackoverflow.com/questions/14226531/what-format-is-for-android-camera-with-raw-picturecallback so maybe `BitmapFactory.decodeByteArray` is the way to go? – Ciro Santilli OurBigBook.com Feb 15 '16 at 21:16

3 Answers3

8

I used the following code to show live camera feed in a layout background and the button saves the image as jpeg. Try and modify it as you wish : You can download the entire test project here so that you can test it fast : http://www.4shared.com/rar/v-ZQPybcce/Test.html

--->>The difference of this code from others using intents is that it takes the picture automatically without opening the camera app which makes the app look better :) <----

package com.mreprogramming.test;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Toast;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Bitmap.CompressFormat;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.os.Bundle;
import android.os.Environment;
import android.preference.PreferenceManager;


public class CameraActivity extends Activity implements SurfaceHolder.Callback{

    protected static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 0;
    private SurfaceView SurView;
    private SurfaceHolder camHolder;
    private boolean previewRunning;
    private Button button1;
    final Context context = this;
    public static Camera camera = null;
    private ImageView camera_image;
    private Bitmap bmp,bmp1;
    private ByteArrayOutputStream bos;
    private BitmapFactory.Options options,o,o2;
    private FileInputStream fis;
    ByteArrayInputStream fis2;
    private FileOutputStream fos;
    private File dir_image2,dir_image;
    private RelativeLayout CamView;

    @SuppressWarnings("deprecation")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.camera);



    CamView = (RelativeLayout) findViewById(R.id.camview);

    SurView = (SurfaceView)findViewById(R.id.sview);
    camHolder = SurView.getHolder();
    camHolder.addCallback(this);
    camHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    button1 = (Button)findViewById(R.id.button_1);


    camera_image = (ImageView) findViewById(R.id.camera_image);


    button1.setOnClickListener(new OnClickListener()
    {

    public void onClick(View v)
    {

        button1.setClickable(false);
        button1.setVisibility(View.INVISIBLE);  //<-----HIDE HERE 
        camera.takePicture(null, null, mPicture);

    }

    });


    }




    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
        int height) {
    if(previewRunning){
        camera.stopPreview();
    }
    Camera.Parameters camParams = camera.getParameters();
    Camera.Size size = camParams.getSupportedPreviewSizes().get(0); 
    camParams.setPreviewSize(size.width, size.height);
    camera.setParameters(camParams);
    try{
        camera.setPreviewDisplay(holder);
        camera.startPreview();
        previewRunning=true;
    }catch(IOException e){
        e.printStackTrace();
    }
    }

    public void surfaceCreated(SurfaceHolder holder) {
    try{
        camera=Camera.open();
    }catch(Exception e){
        e.printStackTrace();
        Toast.makeText(getApplicationContext(),"Error",Toast.LENGTH_LONG).show();
        finish();
    }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
    camera.stopPreview();
    camera.release();
    camera=null;
    }



    public void TakeScreenshot(){

        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
        int nu = preferences.getInt("image_num",0);
        nu++;
        SharedPreferences.Editor editor = preferences.edit();
        editor.putInt("image_num",nu);
        editor.commit();
        CamView.setDrawingCacheEnabled(true); 
        CamView.buildDrawingCache(true);
        bmp = Bitmap.createBitmap(CamView.getDrawingCache());
        CamView.setDrawingCacheEnabled(false);
                        bos = new ByteArrayOutputStream(); 
                        bmp.compress(CompressFormat.JPEG, 100, bos); 
                        byte[] bitmapdata = bos.toByteArray();
                        fis2 = new ByteArrayInputStream(bitmapdata);

                        String picId=String.valueOf(nu);
                        String myfile="MyImage"+picId+".jpeg";

                        dir_image = new  File(Environment.getExternalStorageDirectory()+
                                File.separator+"My Custom Folder");
                        dir_image.mkdirs();

                        try {
                            File tmpFile = new File(dir_image,myfile); 
                            fos = new FileOutputStream(tmpFile);

                             byte[] buf = new byte[1024];
                                int len;
                                while ((len = fis2.read(buf)) > 0) {
                                    fos.write(buf, 0, len);
                                }
                                    fis2.close();
                                    fos.close();

                                    Toast.makeText(getApplicationContext(),
                                            "The file is saved at :/My Custom Folder/"+"MyImage"+picId+".jpeg",Toast.LENGTH_LONG).show();

                                    bmp1 = null;
                                    camera_image.setImageBitmap(bmp1);
                                    camera.startPreview();
                                    button1.setClickable(true);
                                          button1.setVisibility(View.VISIBLE);//<----UNHIDE HER
                        } catch (FileNotFoundException e) {
                            e.printStackTrace();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }


    }

    private PictureCallback mPicture = new PictureCallback() {

        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            dir_image2 = new  File(Environment.getExternalStorageDirectory()+
                    File.separator+"My Custom Folder");
            dir_image2.mkdirs();


            File tmpFile = new File(dir_image2,"TempImage.jpg");
            try {
                fos = new FileOutputStream(tmpFile);
                fos.write(data);
                fos.close();
            } catch (FileNotFoundException e) {
                Toast.makeText(getApplicationContext(),"Error",Toast.LENGTH_LONG).show();
            } catch (IOException e) {
                Toast.makeText(getApplicationContext(),"Error",Toast.LENGTH_LONG).show();
            }
            options = new BitmapFactory.Options();
            options.inPreferredConfig = Bitmap.Config.ARGB_8888;

                bmp1 = decodeFile(tmpFile);
                bmp=Bitmap.createScaledBitmap(bmp1,CamView.getWidth(), CamView.getHeight(),true);
                camera_image.setImageBitmap(bmp);
                tmpFile.delete();
                TakeScreenshot();

        }
    };


    public Bitmap decodeFile(File f) {
        Bitmap b = null;
        try {
            // Decode image size
            o = new BitmapFactory.Options();
            o.inJustDecodeBounds = true;

            fis = new FileInputStream(f);
            BitmapFactory.decodeStream(fis, null, o);
            fis.close();
            int IMAGE_MAX_SIZE = 1000;
            int scale = 1;
            if (o.outHeight > IMAGE_MAX_SIZE || o.outWidth > IMAGE_MAX_SIZE) {
                scale = (int) Math.pow(
                        2,
                        (int) Math.round(Math.log(IMAGE_MAX_SIZE
                                / (double) Math.max(o.outHeight, o.outWidth))
                                / Math.log(0.5)));
            }

            // Decode with inSampleSize
            o2 = new BitmapFactory.Options();
            o2.inSampleSize = scale;
            fis = new FileInputStream(f);
            b = BitmapFactory.decodeStream(fis, null, o2);
            fis.close();

        } catch (IOException e) {
            e.printStackTrace();
        }

        return b;
    }


}

This is the camera.xml

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" 
android:id="@+id/camview">

<SurfaceView
android:id="@+id/sview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true" />

<ImageView
    android:id="@+id/camera_image"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:contentDescription="@string/app_name" />

<Button
    android:id="@+id/button_1"
    android:layout_width="20dp"
    android:layout_height="20dp"
    android:layout_alignParentLeft="true"
    android:layout_alignParentTop="true" />

Add this to your manifest :

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

Also in the manifest add the following to the "CameraActivity" activity tab to make sure that your activity will always be in landscape orientation because otherwise holding the phone in protrait(upright) unless you change the code it will reverse the image's aspect ratio and severely distort it.

<activity
        android:name="com.mreprogramming.test.CameraActivity"
        android:label="@string/app_name"
        android:screenOrientation="landscape" >   <-------ADD THIS ---!!!!!
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

And save this as styles.xml to make your layout fullscreen

<resources>

<!--
    Base application theme, dependent on API level. This theme is replaced
    by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
-->
<style name="AppBaseTheme" parent="android:Theme.NoTitleBar.Fullscreen">
    <!--
        Theme customizations available in newer API levels can go in
        res/values-vXX/styles.xml, while customizations related to
        backward-compatibility can go here.
    -->
</style>

<!-- Application theme. -->
<style name="AppTheme" parent="android:Theme.NoTitleBar.Fullscreen">
    <item name="android:windowFullscreen">true</item>
    <item name="android:windowNoTitle">true</item>
</style>

In my app i want the image to capture every view of the layout not just the camera feed like this : enter image description here

The test code I posted here hides the capture button so that it wont appear in your photo. If you have more views in your app and don't won't them to show in the photo either hide them while capturing (see code to know where to hide) or edit the code.

------>To sum up my post this code can do the basic capturing and saving a jpeg but if you want professional images you need to edit it a bit. Good Luck :)<------

mremremre1
  • 1,036
  • 3
  • 16
  • 34
  • 1
    "takes the picture automatically without opening the camera app" - thats important, I will try this the next days:) – moobi May 28 '14 at 23:41
  • @SimonIrsch I added download link so that you can get the test project as is and load it to your eclipse fast – mremremre1 May 29 '14 at 02:38
  • @mremremre1 Thanks for sharing your code. Could you give a hint where I should add a function if I want to classify every image seen by the android camera without the need of pushing the button? In other words: Where do I have to move the method `camera.takePicture(null, null, mPicture);` such that it gets called in a infinite loop. Also your download link seems to be broken – mcExchange Apr 26 '16 at 20:23
  • The easiest solution to get a bitmap by default using Camera is to set Camera.Parameters.setPictureFormat(ImageFormat.JPEG) from your Camera instance... you can still change it's rotation and jpeg quality. – Ely Dantas Jun 22 '18 at 21:50
5

I don't know if this solution is what you want. However the basics to take a picture as bitmap should be like this:

 private static final int CAMERA_REQUEST = 1888; // field

 private void takePicture(){ //you can call this every 5 seconds using a timer or whenever you want
  Intent cameraIntent = new  Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); 
  startActivityForResult(cameraIntent, CAMERA_REQUEST); 
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
    super.onActivityResult(requestCode, resultCode, data); 
    if (requestCode == CAMERA_REQUEST && resultCode == Activity.RESULT_OK) {  
        Bitmap picture = (Bitmap) data.getExtras().get("data");//this is your bitmap image and now you can do whatever you want with this 
        imageView.setImageBitmap(picture); //for example I put bmp in an ImageView
    }  
} 

Don't forget to set permission for camera in your Manifest:

<uses-feature android:name="android.hardware.camera" />
Augusto Picciani
  • 788
  • 2
  • 11
  • 31
  • 1
    I tried something like that. It opens the standard camera application on the device, doesnt it? If yes, I cant use it, because I like my app to take pictures automatically and inside my app! – moobi May 28 '14 at 23:38
  • 2
    Ok so you want to take picture without user interaction (i think android does not allow you to take picture without preview) using front cam. See this if could help you: http://stackoverflow.com/questions/9752730/take-a-photo-automatically-without-user-interaction – Augusto Picciani May 28 '14 at 23:52
  • @AugustoPicciani that thread seems to ask mostly about saving a jpeg to disk, which is easier since `camera.takePicture` returns jpeg. But it did teach me about `BitmapFactory.decodeByteArray`. – Ciro Santilli OurBigBook.com Feb 15 '16 at 21:18
  • 3
    This only gets the thumbnail bitmap and not the full size picture! – Rasovica Jun 09 '17 at 18:50
  • 2
    it is working perfectly but why uploaded image size so small – Amit Kumar Pawar Oct 31 '18 at 08:00
-1

You should first take the picture by using an IMAGE_CAPTURE Intent

Then you will want to create a temporary file to store the photo at so it doesn't use all of the memory on the phone.

After that, grab the Bitmap using android.provider.MediaStore.Images.Media.getBitmap() and select the temporary file.

Here is a full code example on how to do it:

Android Camera Intent: how to get full sized photo?

Community
  • 1
  • 1
MJ93
  • 4,966
  • 8
  • 32
  • 50