I have spent several weeks trying to get photographs programmatically from an android
camera, with FMX and Delphi.
Here are a couple of my observations from this work, along with a wish list (or was that
whinge list?).
There are two reasonably accessible ways of accessing an android camera:
(1) via CameraComponent
(2) via ActionList / TakePhotoFromCameraAction
Each has its advantages and disadvantages.
First: CameraComponent:
Use:
Insert a tCameraComponent component, and a tImage.
This component does not take a picture, such as by pushing a shutter button. It keeps
transferring the image to your image, and in the Object Inspector you have to set up a
routine to synchronise the threads for this, and a routine to transfer the image, as per:
procedure Form.CameraComponentSampleBufferReady(Sender: TObject; const ATime: TMediaTime);
begin
TThread.Synchronize(TThread.CurrentThread, DisplayCameraPreviewFrame);
end;
procedure Form.DisplayCameraPreviewFrame;
begin
CameraComponent1.SampleBufferToBitmap(Image1.Bitmap, True);
end;
Good bits:
This provides access to many of the camera parameters, and is, once you get the hang of it,
not too hard to drive. Unfortunately it is missing a few things. Via the uSettings.pas which
accompanies the demo programme, access can be made to a lot of camera (and torch) options,
and these work well. It is possible to write your own small routines to let you set up photo
type and quality and torch options before executing CameraComponent. You can put the image
where you want it (in a tImage) and write it out to disc. If you want decent resolution
pictures, you will need to set the MaxHeight and MaxWidth parameters to higher than your
camera resolution, or you only get a 70kB poor resolution picture. The torch access is
excellent, allowing you to have your torch on while you are setting up the picture, which
is most valuable (especially on cameras where the torch is either off or a flash only!)
Bad bits:
The documentation needs further work.
The really big lack is that there is no ability to change the camera zoom. This is a major
shortfall. If it could be implemented as GetZoom, SetZoom, GetMaxZoom and GetMinZoom or
something like this, it would be wonderful!
Some of us would like a manual focus option and setting too (note that in the code there are
hooks for focus, but they are null subroutines).
TakePhotoFromCameraAction:
Use:
Insert a tActionList component, and a tImage.
Double-click on it.
At the top left of the box which appears is a button with a down-arrow beside it. Press
on the down arrow. Then insert aTakePhotoFromCameraAction action.
Double-click on this, so you can see it in the Object Inspector.
Here you can set the MaxHeight and MaxWidth parameters, and put in a routine for what to do
after taking the photo. In that routine, copy the image to your image, so you can save it.
Pros:
This, once you get the hang of setting up a tActionList, it is a relatively easy beast to
programme. It takes higher resolution pictures than CameraComponent (after setting the Height
and Width to 8000 it produces .jpg files of over 1Mb). You have access to all the camera
basic options, though you have no way of setting defaults before executing it.
Cons:
Again, the documentation was inadequate for those who have no idea of how to use it. It talks
about the image being available at the end of taking a photo, but you have to chase up the example
to find out enough about it to be able to use it. The image provided (and I suspect that this is
due to actually running the androidâs camera programme, and may not be anything Delphi has any
control over) fills the whole screen, sometimes making it quite hard to see the options and the
âOKâ and âRetryâ buttons, especially in bright sunshine.
With either of them, the MultiResBitmap provided by either of these may have 1 or 2 bitmaps in it.
If there is one, no problems. If there are two, make sure you write the one with a width > 0, as
per the following code:
//If we use
// Image1.Bitmap.SaveToFile(WorkingDirectory + s + '.' + EditExt.Text);
// it prangs (zero length file if .jpg extension used) on the Samsung S22 phone.
m := Image1.MultiResBitmap.Count;
i := 0;
if m > 0 then begin
for i := 0 to m - 1 do
if round(Image1.MultiResBitmap.Items[i].Bitmap.Width) > 0 then break;
Image1.MultiResBitmap.Items[i].Bitmap.SaveToFile(PhotoDirectory + s + '.' + EditFileExt.Text);
I hope this is some use to others tearing their hair out trying to take piccies!