TakePicture - Using the internal camera from your application

Erel

B4X founder
Staff member
Licensed User
Longtime User
I wanted to be able to take pictures using the internal camera of an Asus P750 right from my application.
I've first tried the "native" approach and downloaded the code of Wimo (worth a look).
However the pictures taken were distorted and the whole process was unstable (crashing from time to time).
My second attempt was to call the CameraCaptureDialog which has a "managed" api. Dzt has already created a wrapper for it: http://www.b4x.com/forum/additional-libraries/1155-ccd-camera-library.html#post6033
I wanted to show the camera dialog and then send a keypress message that will take the picture and then somehow close the dialog.
However this didn't work as well, throwing InvalidOperationException every time.
After searching a little bit it is clear that it is a common problem and this api is not supported by all devices.

The third attempt seems to work.
Instead of calling the CameraCaptureDialog we are launching camera.exe.
The drawback is that we can't change the default settings like resolution and file name.

Using a timer we are waiting 5 seconds before sending the "Ok" key message which takes a picture and then after another 5 seconds we close the process with Process.CloseMainWindow.

This program requires agraham's threading library (only for the Process object).
The source code is attached.

B4X:
Sub Globals
    tick = 0
End Sub

Sub App_Start
    Form1.Show
    process.New1
    hardware.New1
    timer1.Interval = 5000
End Sub

Sub btnTakePicture_Click
    timer1.Enabled = True
    process.Start("\windows\camera.exe","")
End Sub

Sub AfterPicture
    file = FindLastFile("\my documents\my pictures\","pic")
    label1.Text = FileName(file)
    image1.Image = file
End Sub
Sub FindLastFile (path, prefix)
    ArrayList1.Clear
    FileSearch(ArrayList1,path,prefix & "*.jpg")
    'We assume that the last taken image name will be the last name in the sorted list.
    'This assumption might be wrong.
    ArrayList1.Sort(cCaseSensitive)
    Return ArrayList1.Item(ArrayList1.Count-1)
End Sub

Sub Timer1_Tick
    tick = tick + 1
    If tick = 1 Then 'take picture
        hardware.KeyPress(13)
    Else
        timer1.Enabled = False
        process.CloseMainWindow
        tick = 0
        AfterPicture
    End If
End Sub
 

Attachments

  • TakePicture.sbp
    1.4 KB · Views: 559

JOTHA

Well-Known Member
Licensed User
Longtime User
Hi Erel,
thank yo very much for this application:
I wanted to be able to take pictures using the internal camera of an Asus P750 right from my application.

At the first download, it worked on the Desktop-PC, but not on the Pocket-PC, because the "Hardware.DLL" was not installed automatically.

Then I copied the "Hardware.DLL" onto the Pocket-PC.

1) The application started.
2) When clicking the Button "TakePicture", the internal camera started.
3) It seems, that the camera made a photo by itself (without pressing any key).
4) Then came this Error-Message: :confused:
 

Attachments

  • TakePicture - Error.jpg
    TakePicture - Error.jpg
    27.1 KB · Views: 384

JOTHA

Well-Known Member
Licensed User
Longtime User
Hi Erel,

thank you for your help.

I did what you told me:

You should change line 18 to the path used in your device, and also to the same prefix that is set in the camera settings.
B4X:
    file = FindLastFile("\my documents\my pictures\","pic")

I changed the path into ...
B4X:
file = FindLastFile("\My Documents\Meine Bilder\","jpg")
... after that there was another error-message, so I thought I did a mistake.

Then I changed the path into ...
B4X:
file = FindLastFile("\Speicherkarte\DCIM\100MEDIA\","jpg")
... and the same error-message came again.

On my Pocket-PC I don´t have a choice by my own to set the path. I have an AMEO (= HTC ADVANTAGE X 7500) and there are 3 possible choices.
1) Gerät [= Device] The path is: ("\My Documents\Eigene Bilder\",jpg")
2) Speicherkarte [= Mini SD-Card] The path is: ("\Speicherkarte\DCIM\100MEDIA\",jpg")
3) MicroDrive [= built in 8 GB Drive] I didn´t try it yet.

--> Certainly I had a look at the right path (where the taken pictures were sent to).

The error-message was:
An error occurred on sub main.findlastfile.
Line number: 40
Return
ArrayList1.Item(ArrayList1.Count-1)
Error description:
Es kann keine Fehlermeldung angezeigt werden, da die optionale Ressource der Assembly, die die Fehlermeldung enthält, nicht gefunden wurde.
Continue?

Thank you in Advantage!
 
Last edited:

JOTHA

Well-Known Member
Licensed User
Longtime User
Hi Erel,

:sign0013: I´m very sorry to have wasted your time!

... So 'pic' is the prefix (beginning) of the names.

I made a mistake because I thought you meant the suffix.
In Germany we say: "If someone can read, he has the advantage!"

Thank you again - now it works! :)
 

taximania

Well-Known Member
Licensed User
Longtime User
This modified version of Erel's code works on my XDA.
'Modify the pictures location to suit your device.'
All it does is check the directory, and loads the newest picture,
(the one that's just been took).
Green bit below is optional.


B4X:
Sub Globals
 tick = 0
End Sub

Sub App_Start
 Form1.Show
 process.New1
 hardware.New1
 timer1.Interval = 5000
End Sub

Sub Button1_Click
 timer1.Enabled = True
process.Start("\windows\camera.exe","")
End Sub

Sub AfterPicture
 ArrayList1.Clear
 FileSearch(ArrayList1,"[COLOR="Blue"]\Storage Card\My Documents\My Pictures\[/COLOR]","*.jpg")
 file=ArrayList1.Item(arraylist1.Count-1)
 [COLOR="lime"]label1.Text = file 'full path and file name
 'label1.Text = FileName(file) 'just file name[/COLOR]
 image1.Image = file
End Sub

Sub Timer1_Tick
 tick = tick + 1
 If tick = 1 Then 'take picture
  hardware.KeyPress(13)
 Else
  timer1.Enabled = False
  process.CloseMainWindow
  tick = 0
  AfterPicture
 End If
End Sub
 

Attachments

  • TakePicture.sbp
    1.2 KB · Views: 381
Last edited:

JOTHA

Well-Known Member
Licensed User
Longtime User
Hi taximania,

thank you for your version. It works good!

I made a little workaround with yours an Erels code.

- Now you can change the location where the pictures are stored. (green)
- Now you can press the hardbutton to take a photo by yourself.
- It is made as a module, so you can implement it better to your apps.
- ... and some other little changes ...

The shell is in german, if someone needs it in english, please post here.

I hope it is helpful for someone.

Have fun!

B4X:
'------------------------------------------------------
'Modul BildAufnahme
'Build 0066
'------------------------------------------------------
'benötigt Hardware.dll
'benötigt HardwareDesktop.dll
'benötigt Threading.dll
'benötigt Objekt "hardware" aus Hardware
'benötigt Objekt "process" aus Process
'------------------------------------------------------
Sub Globals
    tick = 0
End Sub
'------------------------------------------------------
Sub BildAufnahme_Show
   process.New1
   hardware.New1
    Timer1.Interval = 5000
End Sub
'------------------------------------------------------
Sub Button1_Click
   PanelEinstellungen.Visible = False
   If cPPC Then
   i = Msgbox ("Wollen Sie jetzt die Kamera starten?", " Hinweis", cMsgboxYesNo, cMsgboxQuestion)
    If i = cYes Then
    Panel1.Visible = True
   Button1.Visible = False
    Button3.Visible = True
    End If
    Else
    Msgbox ("Bilder aufnehmen funktioniert nur auf dem Pocket-PC mit eingebauter Kamera.", "Hinweis", cMsgboxOK, cMsgboxExclamation)
   End If 
End Sub
'------------------------------------------------------
Sub AfterPicture
    ArrayList1.Clear
    FileSearch(ArrayList1,[COLOR="Lime"]""&Speicherort.Text&"","*.jpg")[/COLOR]
    file = ArrayList1.Item (ArrayList1.Count-1)
    Label1.Text = file
    Image1.Image = file
   WaitCursor (False)
End Sub
'------------------------------------------------------
Sub Button2_Click
    WaitCursor (True)
'   Panel3.Visible = True
    AfterPicture
   Button2.Visible = False
   Label7.Visible = True
End Sub
'------------------------------------------------------
Sub Button3_Click 'Button "Weiter" nach der Anleitung
    WaitCursor (True)
    Timer1.Enabled = True
   Timer1_Tick
    Shell ("Camera.exe", "")
    Panel1.Visible = False
   Button1.Visible = False
   Button2.Visible = True
   WaitCursor (False)
End Sub
'------------------------------------------------------
Sub Timer1_Tick
    tick = tick + 1
    If tick = 1 Then 'Panel2 "Kamera wird gestartet" zeigen
    Panel2.Visible = True
    Else
    Timer1.Enabled = False
    Panel2.Visible = False
    tick = 0
    End If
End Sub
'------------------------------------------------------
'Einstellungen des Speicherorts für Bilder
'------------------------------------------------------
Sub ButtonEinstellungen_Click
    ButtonEinstellungen.Visible = False
   PanelEinstellungen.Visible = True
End Sub

Sub ButtonEinstellungenSchliessen_Click
    ButtonEinstellungen.Visible = True
   PanelEinstellungen.Visible = False
End Sub
'------------------------------------------------------
'Bild im Verzeichnis löschen
'------------------------------------------------------
Sub ButtonLoeschen_Click
    ArrayList1.Clear
End Sub
 

Attachments

  • B4P - BildFoto.zip
    16 KB · Views: 442

JOTHA

Well-Known Member
Licensed User
Longtime User
Sometimes there is a error-message ...

Hello Erel,

after I changed some details and put it into my app, there was an error message.

So I thought it was my fault.

Then I tried your original-code again, but with one change: the place where the photo is stored (see blue colored):

B4X:
[COLOR="YellowGreen"]'Original von Erel - Build 0002[/COLOR]

Sub Globals
   tick = 0
End Sub

Sub App_Start
   Form1.Show
   process.New1
   hardware.New1
   timer1.Interval = 5000
End Sub

Sub Button1_Click
   timer1.Enabled = True
   process.Start("\windows\camera.exe","")
End Sub

Sub AfterPicture
   file = FindLastFile[COLOR="Blue"]("\Speicherkarte\DCIM\100MEDIA\","imag")[/COLOR]
   label1.Text = FileName(file)
   image1.Image = file
End Sub
Sub FindLastFile (path, prefix)
   ArrayList1.Clear
   FileSearch(ArrayList1,path,prefix & "*.jpg")
   'We assume that the last taken image name will be the last name in the sorted list.
   'This assumption might be wrong.
   ArrayList1.Sort(cCaseSensitive)
   Return ArrayList1.Item(ArrayList1.Count-1)
End Sub

Sub Timer1_Tick
   tick = tick + 1
   If tick = 1 Then 'take picture
      hardware.KeyPress(13)
   Else
      timer1.Enabled = False
      process.CloseMainWindow
      tick = 0
      AfterPicture
   End If
End Sub

I didn´t change anything else, but this error message was shown:

An error occurred on sub main.afterpicture.

Line Number: 22

image1IOmage = file
Error description;
OutOfMemoryExpection
Continue?

After a softreset it worked again for one time. After that it didn´t work again. I closed the app, but the message error was repeated again.

I closed the app again and opened it again - then it worked again!

One thing is really for sure: you have to close the app, if you want to take another photo.

Is there a way to make it more stable?
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
What resolution does your camera use?
When you load an image file the image file is converted to a raw bitmap. So even if the jpg file is not large, the memory it takes can be too large.

You can use a Bitmap object from the ImageLib library to store the image and before loading a new image dispose the old one:
B4X:
Sub App_Start
  Bitmap1.New2(1,1) 'Create a dummy image.
End Sub

'After Picture
Bitmap1.Dispose
AddObject("Bitmap1","Bitmap")
Bitmap1.New1(file)
Image1.Image = Bitmap1.Value
 

tsteward

Well-Known Member
Licensed User
Longtime User
Hello Jotha,
Please post English version of your code

Thanks
 

jesb4ppc

Member
Licensed User
Invalid Operation.

Hi Erel, Taximania, Agraham et. al.

I've been trying to make the TakePicture program to run, with no success.

If I use the "process.CloseMainWindows" I get an error with a lot of messages:

System.Diagnostics.Process.EnsureState()
in
System.Diagnostics.Process.get_HasExited()
in
System.Diagnostics.Process.EnsureState()
in
System.Diagnostics.Process.get_ExitCode()
in
Threading.Process.ExitEvent()
in
System.Diagnostics.Process.OnExited()
in
System.Diagnostics.Process.RaiseOnExited()
in
System.Diagnostics.Process.CompletionCallback()
at
TermWaiter.WaitForTerm()


So, I just tried to start anoher process (calc.exe) to chek it, with the same result.
:confused:
If I use "process.Kill", it works 1 time, and then it says " the camera is in use", but camera doesn't appear on the Programs in execution.

Is it needed to use WM 6, or .net CF 3.5 to make it run, or what am I doing wrong?:sign0085:


I'm using an HTC P3600, with .Net CF 2.0 and WM 5.0

Could you help me with this?
 

jesb4ppc

Member
Licensed User
Threading Process error

Hi agraham,

Nice to hear from you again. :)

Yes, this is what happens. I've test also in a device with WM 6.1 and .Net CF 3.5 with same result.

Calculator starts ok, but only can stop it with "process.Kill", no way with "process.CloseMainWindow"

It's even worse with camera.exe, 'cause camera can only be used the first time.

:confused:

This is the code:

'Basic threading.
' 8 may 2009.

Sub Globals
tick = 0
prog ="\windows\calc.exe"
End Sub

Sub App_Start
Form1.Show
process.New1
hardware.New1
timer1.Interval = 5000
End Sub

Sub Button1_Click
timer1.Enabled = True
process.Start(prog,"")
End Sub

Sub Timer1_Tick
tick = tick + 1
If tick = 1 Then 'Send Intro
hardware.KeyPress(13)
Else
timer1.Enabled = False
process.CloseMainWindow
tick = 0
End If
End Sub


Thank you for your time.
 

agraham

Expert
Licensed User
Longtime User

jesb4ppc

Member
Licensed User
Threading Process error. SOLVED.

Hi agraham,

After using version 1.5 of your library, it runs like a charm, with WM 5.0 and .Net CF 2.0 and also with WM 6.1 and CF 3.5. :)

Reading your post #46 on Threading library for optimising compiler subforum, it seems that once again, Microsoft don't tell the whole truth, or doesn´t write the right documentation.

Fortunaly, you are able to deal with it, and win the challenge.

Once again, thank you very much!

:sign0188:
 

wm.chatman

Well-Known Member
Licensed User
Longtime User
@Jotha - BildFoto.zip

:) Hello Jotha

I found your Bild Foto App and would like to use it in my TRUIDbase App. Device = MDA Pro.
Question: do you have a Update on your BildFoto Program? Or are there still problems with the Program?
If you do have a functional Bild Foto Program, could I ask you to post the newest Version.
This would really be of great help. Thank you Jotha.

Best regards
William
 
Top