A few years ago I started a project for native camera support for Android using the Camera 2 API, partly because the built-in camera support for Delphi was underperforming greatly. I have resurrected the project, added support for iOS, and it is now included in Kastri.
Existing camera support in Delphi
As many of you are probably aware, the existing camera support in Delphi is not very performant, especially on Android. Erik Van Bilsen of Grijjy has provided some hints and workarounds to increase performance, however it still has a way to go.
Camera support in Kastri
Camera support in Kastri builds on the original standalone camera project, and adds support for iOS. On both platforms, instead of using the built-in camera app on devices, native APIs are used. Native controls are also used for displaying the camera preview, so the result is an huge improvement over the existing support in Delphi.
Some caveats
Please be aware that this is a “first release” of camera support. It provides basic turn on/off of the preview, capturing of a still image, and inclusion of location metadata. Other features will be added over time, including:
- Face detection – some of the code is already present; it just needs to be finished/tested
- Providing a list of supported resolutions
- Flash mode on/off
- Focus control
etc. Developers are welcome to contribute to these enhancements, and sponsorship of Delphi Worlds on Github helps make new features a reality.
Also be aware that the Android support requires Android 6.0 or greater, and iOS support requires iOS 10.0 or greater.
Demo
The demo for camera support is here, and is dependent on the Kastri library. When you run the demo you may note that when it is in preview mode, there are controls that appear above the preview. These are image controls that use native APIs to display the images, which makes it possible for them to overlay the native preview control. At present, these controls are created at runtime, however the plan is to change them into components that can install into Delphi.
Switching the Include Location switch starts the location sensor, and will prompt for permissions. Tapping the Start button starts the camera preview. Tapping the Camera button in the middle at the bottom captures an image. Tapping the Swap Camera button in the bottom right changes between front and back cameras.
Once an image is captured, tapping the green Accept button in the top right takes you back to the start, and fills the image control with the captured image. Tapping the red Cancel button in the top right takes you back to the start without filling the image control.
Capturing an image, and Including location metadata
When capturing a still image, the image data is returned in a stream, rather than a bitmap. This is so that metadata can be included, because bitmaps do not have metadata. If you wish to include location data in the image, set the IncludeLocation property of the TCamera instance to True, and before the still is captured, set the Location property to the current coordinates.
You can use Delphi’s TLocationSensor to obtain the users location. Remember that it takes a few seconds for the first location event to fire, start the sensor well before the user is able to capture an image. Please use the demo as a guide.
Remember also that when assigning the image stream to a bitmap, the location data will be lost in the bitmap, as it does not store it.
Note: For Delphi 10.4 and 10.4.1 users, if you wish to use location services on iOS, you will need to patch the System.iOS.Sensors unit as per this report, in order for it to work properly.
Now why does Embarcadero not provide this level of API integration out of the box? This should be baked into the standard product.
Probably because it’s a substantial amount of work. For example, this kind of support is not provided “out of the box” in Android Studio or Xcode – developers need to implement it for themselves, or find 3rd party support.
dw.camera file cannot be found in github
So weird.. I swear those files were checked in. They are now, thanks!
Cant save image in your camera demo.
Get error “Stream read error”
Bitmap width and height are zero.
Hi Dave,
I’m trying to use your Camera demo as a basis for a Barcode Scanner using ZXing. I thought I would use a timer to trigger a CaptureImage event every 250ms and use the result in the CameraImageCapturedHandler to process the image. There appears to be a threading problem so I commented out the ZXing code but I’ve noticed the update rate of the camera output is now very slow and jittery. Am I using the wrong Handler? What I’m trying do do is a screen capture every, say, 250ms, and process the bitmap.
On a side issue are there any functions for converting TNativeImages to TBitmaps?
regards, mike.
The OnCapturedImage event is meant for single image captures, not continuous. Unfortunately on Android it’s very slow, partially due to rotating the image to the correct orientation, and I’m looking into improving the algorithm, however I doubt that it would end up being suitable for what you want to do. I’ll take a look into implementing continuous capture.
Great tool. . . native access like that is very good ..
I have a doubt:
Whenever I take a photo, the image is not in the correct position. The image ends up rotating automatically, being different from the position we took the photo.
How can I adjust this?
or is it a problem in Kastri?
Hi Dave,
I am trying to run your sample on Android10 and Android9, but at runtime, when click on Start button the app crash.
Running on debug mode, I got “EJINIException java.lang.IllegalArgumentException: Surface was abandened” sometimes.
Delphi version 10.3.3.
Is there any know issue?
Thanks in advance
Yes, it’s a known issue. Please refer to: https://github.com/DelphiWorlds/Kastri/issues/20