Working with Embedded Wizard: Displaying dynamically loaded images
Usually the image contents necessary in the GUI application are represented by corresponding bitmap resource members. By using those resource members, you can incorporate in your project any arbitrary number of image files (PNG, JPG, BMP or GIF). During code generation or prototyping the image files are automatically converted in format optimized for your particular target system. This includes the adequate color conversion and compression. This approach is as such optimal for all static image contents, which are known and available at the compilation time.
At the runtime of the application, the content of existing bitmap resources can't be exchanged nor new resources can be added. This prevents the bitmap resources from being suitable to provide image contents determined dynamically at the runtime e.g. loaded from an SD memory card, received from a network adapter or rendered by a third-party application, like the map view in a GPS navigation system.
In order to be able to deal with such demanding application cases, the Mosaic framework provides the class Resources::ExternBitmap. Unlike bitmap resources, objects of this class are optimized to represent and manage image contents being obtained or rendered dynamically at the runtime of the GUI application - thus unknown at the compilation time.
Since Resources::ExternBitmap descends from the class Resources::Bitmap, you can use the Extern Bitmap objects similarly as you do with ordinary bitmap resources. For example, you can assign an Extern Bitmap object to an image, frame, wallpaper, etc. view in order to display its content. Should the content of an Extern Bitmap object change (e.g. after the GPS navigation system has rendered a new map), all affected views are automatically updated.
IMPORTANT
Please note, the class Resources::ExternBitmap depends on an interface you will need to implement in your particular target system. Doing this you will precisely control how the dynamic image contents are found, loaded, decoded and eventually color converted. It's up to you whether the contents are loaded from an SD memory card, received from a network adapter or rendered dynamically by third-party application. For details regarding the interface implementation please see the chapter Extern Bitmap interface.
Similarly to bitmap resources, you can manage as many Extern Bitmap objects as necessary. For example, in an application intended to show a grid with picture thumbnails loaded at the runtime from an SD memory card, you could maintain for every grid cell an individual Extern Bitmap object. When the user scrolls the grid, you only have to take care of the reloading the affected Extern Bitmap objects with new contents. The associated views to display the contents are then updated automatically.
Exact as it is possible with regular bitmap resources, Extern Bitmap objects can represent colored (native) or alpha-only image contents. Moreover, if your application case it requires, Extern Bitmap objects can enclose multi-frame and animated image contents. Finally, the content of an Extern Bitmap object is determined in the implementation of the above mentioned interface to your individual image provider.
The following sections are intended to provide you an introduction and useful tips of how to work with the Extern Bitmap object. For the complete reference please see the documentation of the Resources::ExternBitmap class. Please see also the chapter describing the interface to integrate Extern Bitmap with your particular image provider.
Add new Extern Bitmap object
Depending on your application case, you have the option to add the Extern Bitmap as an embedded object directly to a GUI component or to add it as an autoobject to a unit. The first case is suitable if you want the Extern Bitmap being used locally within the GUI component only. The second case, in turn, is appropriate if you intend to share the Extern Bitmap among multiple GUI components like a kind of common bitmap resource.
To add a new Extern Bitmap object do following:
★Depending on your preferred option switch to the Composer page for the respective GUI component class or the unit where you want to add the Extern Bitmap object.
★Then ensure that the Templates window is visible.
★In Templates window switch to the folder Resources.
★In the folder locate the template Extern Bitmap.
★Drag & Drop the template into the Composer window:
★Eventually name the new added Extern Bitmap object.
Inspect the Extern Bitmap object
As long as the Extern Bitmap object is selected you can inspect and modify its properties conveniently in the Inspector window as demonstrated with the property Name in the screenshot below:
This is in so far worth mentioning as the following sections describe features of the Extern Bitmap object by explicitly referring to its corresponding properties. If you are not familiar with the concept of a property and the usage of Inspector window, please read first the preceding chapter Compositing component appearance.
Specify the content of the Extern Bitmap object
The content, the Extern Bitmap object represents at the runtime is determined by its property Name. This property is declared with string as data type. Accordingly you can initialize it with any text to identify the desired image content within your project. Empty string "", however, is per default understood as no particular content (empty image).
For example, if in your device the image contents are loaded from an SD memory card, the initialization of the property Name could be the path to the desired file on the SD card file system. If the image contents are received over the network, the Name could be an URL addressing precisely the file to download from a server.
Finally it's up to you how the property Name is used. You should understand, that whatever value you assign to this property, this value will be passed 1:1 as parameter to the interface where your individual image content provider is integrated. As such you are free how the value of the property Name is interpreted. In more sophisticated application cases you can use the property even to encode additional parameters, the implementation of your interface can evaluate to prepare the image in the right manner.
For example, an application intended to show images from an SD memory card can use the property Name to address the corresponding file on the file system and to specify an optional flag indicating whether you want the image in its original size or as small thumbnail. Initializing the property with the value "/IMAGE123.JPG" could be understood by the interface as provide the content of the image file IMAGE123. In turn the value "/IMAGE123.JPG (THUMB)" could be understood by the interface as provide the thumbnail content of the image file IMAGE123. Here the additional suffix (THUMB) could be understood as instruction for your image provider to decode the file as thumbnail.
Changing the property Name triggers the affected Extern Bitmap object to reload its content. This involves an invocation of the above mentioned interface to your individual image provider. Once the image loading is finished all views associated actually with the Extern Bitmap object are automatically notified to update their appearance. Thereupon, the new image content is displayed.
Use the Extern Bitmap object
Every Extern Bitmap object is represented at the runtime by an instance of the Mosaic class Resources::ExternBitmap. As such the Extern Bitmap objects can be involved within Chora expressions wherever an operand of the mentioned Mosaic class is expected. It can, for example, be assigned to a Bitmap property of a view able to display images. Moreover, the properties exposed by the Resources::ExternBitmap class can be evaluated. Let's assume, the Extern Bitmap object exists as an embedded object within the actual component, then you can:
// Assign the Extern Bitmap object 'Thumbnail' to an image view SomeImageView.Bitmap = Thumbnail; // Evaluate the properties of the Extern Bitmap object var point size = Thumbnail.FrameSize; var int32 noOfFrames = Thumbnail.NoOfFrames;
If you have put the Extern Bitmap object directly within a unit creating thus an autoobject, you access it exactly as you do with other global entities. In particular, the Extern Bitmap object is identified by its full name, composed of the unit name, the object is defined inside, and the name of the object itself, both separated by :: (double colon) signs. For example:
// Assign the global autoobject 'Example::Thumbnail' to an image view SomeImageView.Bitmap = Example::Thumbnail; // Evaluate the properties of the Extern Bitmap object var point size = Example::Thumbnail.FrameSize; var int32 noOfFrames = Example::Thumbnail.NoOfFrames;
Please note, the properties FrameDelay, FrameSize and NoOfFrames exposed by the Extern Bitmap object are read-only. Trying to modify one of them will result in a runtime error. The properties exist only to query the information associated with the Extern Bitmap object. This information, in turn, is determined just in the moment when the content of an Extern Bitmap object is loaded in the implementation of the interface to your individual image provider.
IMPORTANT
Starting with version 13, the Extern Bitmap object can be configured to perform the loading operation asynchronously. In such case trying to evaluate the attributes of the requested image content immediately after the request has been started will result in zero values since the image contents are not yet available. To deal with such situations you implement the query operation in a slot method associated to the property OnLoaded. See also Load image contents in asynchronous mode for more details.
Lifetime of an Extern Bitmap object
The Extern Bitmap object exists, similarly to other embedded objects and autoobjects as long as it is in use. During this time the image content (the pixel data) represented by the object persists and occupies the memory. If the object is not referenced anymore by any GUI component, the Garbage Collector deletes the object automatically. With this operation also the content of the Extern Bitmap object is released.
TIP
You can force the Extern Bitmap object to release its content early by simply assigning an empty string "" to its property Name. Once the content is released, all views associated with the affected Extern Bitmap object are notified to hide the old contents.
Force an Extern Bitmap object to reload its content
Under normal circumstances, an Extern Bitmap object updates its content only when new value is assigned to its property Name. As long as the value of the property Name doesn't change, the Extern Bitmap object is assumed as containing the same image. In the following example, the Extern Bitmap object Thumbnail is modified, which causes the object to load new image contents and update the appearance of the associated image view:
// Assign the Extern Bitmap object 'Thumbnail' to an image view. The view // will thus display the content of the Extern Bitmap object. SomeImageView.Bitmap = Thumbnail; [...] // Load the 'Thumbnail' object with the image content resulting from the // string 'IMAGE_1'. This will cause the image view 'SomeImageView' to update // its appearance. Thumbnail.Name = "IMAGE_1"; [...] // The object 'Thumbnail' still retains the latest content resulting from // the string 'IMAGE_1'. Accordingly, the image view 'SomeImageView' displays // this content. [...] // Now replace the old content (IMAGE_1) by new content resulting from // the string "IMAGE_6". This causes 'SomeImageView' to update its appearance // automatically. Thumbnail.Name = "IMAGE_6";
In special application cases the image content represented by an Extern Bitmap object may change without the property Name being explicitly modified. Imagine an application intended to display an image received over the network. Now let's assume, the server providing the original image is updated and the image content changes. From the application point of view, the image is still identified by the same URL, so the value of the property Name remains unchanged. The content on the server, however, is modified.
In such case the application has to reload the image again obtaining so its newest version. The Extern Bitmap object provides for this purpose a method Reload(). When you invoke the method, the Extern Bitmap object will simply load a new version of its image content. For example:
// Assign the Extern Bitmap object 'Thumbnail' to an image view. The view // will thus display the content of the Extern Bitmap object. SomeImageView.Bitmap = Thumbnail; // Load the 'Thumbnail' object with the image content resulting from the // given string. This will cause the image view 'SomeImageView' to update // its appearance. Thumbnail.Name = "http://localhost/image_1234.png"; [...] // Later, your application has received a notification that the image on the // server is changed. Trigger the Extern Bitmap object to load a new version // of the image. With this the image view 'SomeImageView' will update its // appearance. Thumbnail.Reload();
Example
The following example demonstrates the usage of the Extern Bitmap object to represent JPG, PNG, etc. images loaded from your PC hard-disc. Please note, in order to find, load and decode the image files, this example includes the adequate implementation of the above mentioned interface between the Extern Bitmap object and the Windows API as so-called intrinsic module. As such, before you can bring-up this example to your particular target system, you will need to take care of the right adaptation of this interface.
Please note, the example presents eventually features available as of version 8.10
Load image contents in asynchronous mode
Before version 13, the loading of external image contents occurred synchronously. That means that the GUI application had to wait being blocked till the contents were available. With the new added property Asynchronous you can instruct the Extern Bitmap object to perform the load operation asynchronously. The request is not blocking anymore. As soon as the image contents are available, all image views referencing the affected Extern Bitmap object are notified to update their appearance.
IMPORTANT
The asynchronous mode requires the underlaying Extern Bitmap loader interface to implement additional functions which start and manage the pending requests. If you plan to use asynchronous mode, you will need to adapt the interface appropriately. For more details see Extern Bitmap interface.
A side effect of the asynchronous mode is, that when the Extern Bitmap object is triggered to load new contents, the contents are not available immediately. Trying to evaluate the size of the image, for example as shown in the code snippet below, will therefore not work:
// Trigger the Extern Bitmap object to load image contents identified by the name // "Image123". The loading is performed asynchronously. ExternBitmap.Asynchronous = true; ExternBitmap.Name = "Image123"; // At this time, the loading not yet started. Trying to evaluate the attributes of // the image will return zero values. var point size = ExternBitmap.FrameSize; // size = <0,0> var int32 noOfFrames = ExternBitmap.NoOfFrames; // noOfFrames = 0
To correctly deal with such application cases, the Extern Bitmap object sends signals to associated slot methods notifying your implementation about the success or fail of the load request. Within the slot method, you can then handle the event and, for example if the loading was successful, query the size of the loaded image content. Following three properties are available where a slot method can be assigned to the Extern Bitmap object:
Property |
Description |
---|---|
The slot method assigned to this property will be notified as soon as the Extern Bitmap object has successfully finalized the loading operation. The new image content is available now. |
|
The slot method assigned to this property will be notified as soon as the loading of the extern image contents has failed for whatever reason. The Extern Bitmap object remains empty thereupon. |
|
The slot method assigned to this property will be notified when the content of the Extern Bitmap object has changed. Unlike OnLoaded it includes also the case of the Extern Bitmap object being cleaned up. |
Query optional information associated to the loaded image content
By using the method GetInfo() it is possible to query an information string associated to the loaded image content. This could be, for example, the description of the image or additional attributes how to display the image, etc. Since the information is represented by a string it can be used flexibly. It's up to you to interpret (decode) the string contents.
IMPORTANT
The use of the GetInfo() method assumes that the Extern Bitmap object is configured to perform the load requests asynchronously. Using GetInfo() in synchronous mode is not possible due to compatibility with older versions.