Android Tutorial Take pictures with the internal camera

Discussion in 'Tutorials & Examples' started by Erel, Dec 14, 2010.

Thread Status:
Not open for further replies.
  1. Erel

    Erel Administrator Staff Member Licensed User

    It is recommend to use the new CameraEx class. It provides more functionality.
    The new Camera library allows you to take pictures using the back facing camera.

    The following steps are required for taking a picture:
    - Initialize a camera object. The Initialize method expects a Panel. The preview images will be displayed on this panel.
    - Wait for the Ready event.
    - In the Ready event Sub, call Camera.StartPreview to show the images preview.
    - Call TakePicture to take a picture.
    - The PictureTaken event will be raised with the picture passed as a bytes array (in JPEG format).
    - Call StartPreview again to restart the images preview.

    Only one process can access the camera at a time. Therefore you should release the camera when your activity is paused.
    Usually you will initialize the camera during Activity_Resume and pause it during Activity_Pause.

    [​IMG]

    The following code saves the image:
    Code:
    Sub Camera1_PictureTaken (Data() As Byte)
        
    Dim out As OutputStream
        out = 
    File.OpenOutput(File.DirRootExternal, "1.jpg"False)
        out.WriteBytes(data, 
    0, data.Length)
        out.Close
        
    ToastMessageShow("Image saved: " & File.Combine(File.DirRootExternal, "1.jpg"), True)
    You can see in the attached code that the "take picture" button is only enabled when the camera is ready.

    For now the camera orientation is always set to landscape mode. Usually you will want to force the activity to also be in landscape mode. This is done by checking 'Lansdcape' in Project - Orientations Supported menu.

    On the emulator the preview images will show a moving check board.
     

    Attached Files:

    Ben likes this.
  2. Cor

    Cor Active Member Licensed User

    great

    thanks

    grCor
     
  3. mshihrer

    mshihrer Member Licensed User

    I get an error

    when I run this example, I get an error after I click on the button to take a picture. Here is what it says:

    An error has occurred in sub:main_camera1_picturetaken
    (java line:225)
    java.io.FileNotFoundException: /sdcard/1.jpg
    Continue?

    also, after looking at the code, I noticed there is a SUB that NEVER gets called, the sub is :
    Code:
    Sub Camera1_Ready (Success As Boolean)
       
    If success Then
          Camera1.StartPreview
          btnTakePicture.Enabled = 
    True
       
    Else
          
    ToastMessageShow("Cannot open camera."True)
       
    End If
    End Sub
    not sure what if I am doing something wrong.

    edit:

    unless after you create Camera1, this sub becomes an event. This is so confusing.
     
    Last edited: Feb 16, 2011
  4. Erel

    Erel Administrator Staff Member Licensed User

    The Ready event is clearly described in the first post.

    Do you have an external card mounted? Make sure that it is not locked for some reason (like when the device is connected as a USB storage).
     
  5. mshihrer

    mshihrer Member Licensed User

    ok, thanks, that was it. I still had it connected to usb.
    Sorry about the event question, I get it now. I never noticed the section in the documentation for the libraries that list the events. All good now, thanks again.
     
  6. karmacomposer

    karmacomposer Member Licensed User

    How would we use this to take VIDEO? Also, my tablet has a front facing camera only, will this still work?

    Mike
     
  7. Erel

    Erel Administrator Staff Member Licensed User

    Only still images are supported for now.
    Assuming that Android treats it as the primary camera then it should work properly.
     
  8. jota

    jota Active Member Licensed User

    problem orientation

    Hi, I found that if the orientation of the application is Both the preview does not display if the orientation is Portrait everything goes right. How can we solve this? Thanks


    my English = google translator (sorry)
     
  9. Erel

    Erel Administrator Staff Member Licensed User

    Currently only landscape is supported (this is the native camera orientation).
     
  10. jota

    jota Active Member Licensed User

    And is there any way to change the view of an activity without fixing the view of the entire application?
     
  11. Erel

    Erel Administrator Staff Member Licensed User

    You can manually edit the manifest file and set the orientation property of a specific activity. Then set the file to be read-only so it would not be overwritten.
    The file - AndroidManifest.Xml is located in <source folder>\Objects.
    Code:
    <activity android:windowSoftInputMode="stateHidden" android:launchMode="singleTop" android:name=".main"
                      android:
    label="Flickr Viewer" android:screenOrientation="unspecified">
                <
    intent-filter>
                    <action android:name=
    "android.intent.action.MAIN" />
                    <category android:name=
    "android.intent.category.LAUNCHER" />
                </
    intent-filter>
            </
    activity>
            <
    activity android:windowSoftInputMode="stateHidden" android:launchMode="singleTop" android:name="activity2" android:label="Activity2" android:screenOrientation="unspecified"></activity>
    You should change "unspecified" to "landscape" for the required activity.

    It is recommended to do this change when your application is more or less ready. Once you set the file to read-only it will not get updated with new permissions / updated version number and so on.
     
  12. jota

    jota Active Member Licensed User

    Thank you very much for this alternative, so I'll try.
     
  13. fabianr

    fabianr Member Licensed User

    How I can set the resolution of the photograph?
    By default is 1600x1200 :/
    Thank you.
     
  14. Erel

    Erel Administrator Staff Member Licensed User

    Currently you cannot change it.

    I'm posting the library code. You are all welcomed to modify it:
    Code:
    package anywheresoftware.b4a.objects;

    import java.io.IOException;
    import java.util.concurrent.atomic.AtomicInteger;

    import android.hardware.Camera;
    import android.hardware.Camera.Parameters;
    import android.view.SurfaceHolder;
    import android.view.SurfaceView;
    import android.view.ViewGroup;
    import android.view.ViewGroup.LayoutParams;
    import anywheresoftware.b4a.BA;
    import anywheresoftware.b4a.BALayout;
    import anywheresoftware.b4a.BA.ActivityObject;
    import anywheresoftware.b4a.BA.Events;
    import anywheresoftware.b4a.BA.Permissions;
    import anywheresoftware.b4a.BA.ShortName;
    import anywheresoftware.b4a.BA.Version;
    import anywheresoftware.b4a.keywords.Common;

    /**
     * The 
    camera object allows you to use the device back facing camera to take pictures and show preview images.
     *Currently the 
    camera orientation is always landscape. Usually you will want to force the application to also be in landscape mode (Project - Supported Orientations).
     *Only one process can access the 
    camera at any time. Therefore it is highly recommended to initialize the camera object in Activity_Resume and release it in Activity_Pause.
     *A working example with explanations 
    is available <link>here|http://www.basic4ppc.com/forum/basic4android-getting-started-tutorials/6891-take-pictures-internal-camera.html</link>.
     */
    @ActivityObject
    @Permissions(values={
    "android.permission.CAMERA"})
    @ShortName("Camera")
    @Version(1.0f)
    @Events(values={"Ready (Success As Boolean)", "PictureTaken (Data() As Byte)"})
    public class CameraW {
        private static Camera c;
        private SurfaceView sv;
        private String eventName;
        private BA ba;
        private AtomicInteger readyCount = new AtomicInteger();
        /**
         * Initializes the camera.
         *Panel - The preview images will be displayed on the panel.
         *EventName - Events subs prefix.
         *The Ready event will be raised when the camera has finished opening.
         */
        public void Initialize(final BA ba, ViewGroup Panel, String EventName) {
            this.ba = ba;
            readyCount.set(0);
            this.eventName = EventName.toLowerCase(BA.cul);
            sv = new SurfaceView(ba.context);
            anywheresoftware.b4a.BALayout.LayoutParams lp = new anywheresoftware.b4a.BALayout.LayoutParams(0, 0,
                    Panel.getLayoutParams().width, Panel.getLayoutParams().height);
            Panel.addView(sv, lp);
            if (c != null) {
                readyCount.set(1);
            }
            sv.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
            sv.getHolder().setFixedSize(Panel.getLayoutParams().width, Panel.getLayoutParams().height);
            sv.getHolder().addCallback(new SurfaceHolder.Callback() {

                @Override
                public void surfaceChanged(SurfaceHolder holder, int format,
                        int width, int height) {
                }

                @Override
                public void surfaceCreated(SurfaceHolder holder) {
                    if (readyCount.addAndGet(1) == 2) {
                        ba.raiseEvent(null, eventName + "_ready", true);
                    }
                }

                @Override
                public void surfaceDestroyed(SurfaceHolder holder) {

                }

            });
            if (c == null) {
                ba.submitRunnable(new Runnable() {

                    @Override
                    public void run() {
                        try {
                            c = Camera.open();
                            if (readyCount.addAndGet(1) == 2) {
                                ba.raiseEventFromDifferentThread(null, CameraW.this, -1,eventName +  "_ready", false, new Object[] {true});
                            }
                        }
                        catch (Exception e) {
                            Release();
                            ba.raiseEventFromDifferentThread(null, CameraW.this, -1,eventName +  "_ready", false, new Object[] {false});
                        }
                    }

                }, this, -1);
            }
        }
        /**
         * Starts displaying the preview images.
         */
        public void StartPreview() throws IOException {
            c.setPreviewDisplay(sv.getHolder());
            c.startPreview();
        }
        /**
         * Stops displaying the preview images.
         */
        public void StopPreview() {
            if (c != null)
                c.stopPreview();
        }
        /**
         * Releases the camera object and allows other processes to access the camera.
         */
        public void Release() {
            if (sv != null) {
                ViewGroup vg = (ViewGroup) sv.getParent();
                vg.removeView(sv);
                sv = null;
            }
            if (c != null) {
                c.release();
                c = null;
            }
        }
        /**
         * Takes a picture. When the picture is ready, the PictureTaken event will be raised.
         *You should not call TakePicture while another picture is currently taken.
         *The preview images are stopped after calling this method. You can call StartPreview to restart the preview images.
         */
        public void TakePicture() {
            c.takePicture(null , null, new Camera.PictureCallback() {

                @Override
                public void onPictureTaken(byte[] data, Camera camera) {
                    ba.raiseEvent(null, eventName + "_picturetaken", data);
                }
                
            });
        }



    }
     
  15. JogiDroid

    JogiDroid Member Licensed User

    I found that preview image is bit odd in my ZTE Blade (updated to 2.2 version), it contains both horizontal and vertical black lines if the preview panel is not filling whole screen. Number and placement of weird lines depends size of the preview panel, sometimes there are lot of lines, sometimes just few.
    Mayby just bug in preview image scaling (based on cameralib code I cant see there is much to do.. )
     
  16. droidman

    droidman Member Licensed User

    i tested this and worked out just fine, but is it a way or tutorial how to make effects on the picture?
     
  17. swissmade

    swissmade Active Member Licensed User

    Not all Data Saved

    Hello all,
    I try this sample and it is working fine.
    But when I take a picture not all data is saved.
    I have only a part of the image.
    The rest of the image is grey.:sign0137:

    I use a Sony Xperia Arc with 8mp Camera.
    It seems that we lose some data on the way.

    Please help,
     
    Last edited: May 11, 2011
  18. Erel

    Erel Administrator Staff Member Licensed User

    Are you closing the output stream after saving the file?
     
  19. swissmade

    swissmade Active Member Licensed User

    Hi Erel,

    Yes I close the stream.
    I use the sample from the Forum to test this.

    Sub Camera1_PictureTaken (Data() As Byte)
    camera1.StartPreview
    Dim out As OutputStream
    out = File.OpenOutput(File.DirRootExternal, "1.jpg", False)
    out.WriteBytes(data, 0, data.Length)
    out.Close 'Closing Stream
    ToastMessageShow("Image saved: " & File.Combine(File.DirRootExternal, "1.jpg"), True)
    btnTakePicture.Enabled = True
    End Sub

    I also have the len of data in the image so I think the Camera is not sending all the Data. I check this with msgbox(Data.length,"")

    Hope you can help.
    Thanks
    Also many thanks for your fast respond.

    :icon_clap:
     
  20. Erel

    Erel Administrator Staff Member Licensed User

    The native Camera object is supposed to return a byte array with the complete data. It seems like a bug in your device. Try to restart your device and see if it helps.
     
Thread Status:
Not open for further replies.
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice