Symbian
Symbian OS Library

SYMBIAN OS V9.3

[Index] [Spacer] [Previous] [Next]



Additional ICL Information

This section is intended to provide additional information that would either not fit into any of the previous sections or is common to more than one of them.


Dithering

If a bitmap is decoded to a display mode other than one that is recommended, the image conversion library may use error-diffusion dithering to enable the image to be displayed. A dramatic example of this could be an image originally in 256 colours which is decoded to 16 colours. With error-diffusion dithering the result may look like the following:

Error-diffusion dithering

Error-diffusion dithering

The dithering process can take time, particularly with images such as JPEG where the image is not created in a linear manner row-by-row. Dithering can be bypassed if you do not need to wait and are prepared to allow ICL to map colours to their nearest equivalent. Use the CImageDecoder::EOptionNoDither option during decoder creation to disable dithering, as shown below:

iDecoder = CImageDecoder::FileNewL(iFileSession, iSourceFilename, CImageDecoder::EOptionNoDither);

For more information see, "Scaling and display modes" in Conversion.

[Top]


Threading

The ICL decode and encode classes use background active objects to provide concurrency for the conversion and transformation actions. In addition to the use of active objects, use is also made of threading. There are two instances where threading may be used while using functions of the ICL.

In the first instance where the decoder/encoder plugin has been implemented to use threads, the client application remains essentially unaware of the fact. The calling application can however, request that new threads be used when creating new decoder/encoder objects. This is done by via the EOptionAlwaysThread option during creation of the decoder or encoder, as in:

iDecoder = CImageDecoder::FileNewL(iFileSession, iSourceFilename, CImageDecoder::EOptionAlwaysThread);

Note: If the decoder/encoder already uses separate threads, the EOptionAlwaysThread is ignored.

Consider the following when deciding whether to use separate threads for decoder or encoder object:

For most applications and with well-written plugins active objects freezing the application is not a problem. However, if there is concern about real-time constraints, then using separate threads is an obvious step; the impact on the parent thread during conversion is minimised.

There is one other possible processing bottleneck and that is during the open operation of the decoder object. The decoder can be required to scan the header information of the bitmap to determine the plugin to use; this is done synchronously and can freeze the parent thread for a short period of time. Such scanning is usually quick, and is not believed to be a major problem. If an application wishes to avoid any such problems it should implement threading itself. It could then start a separate thread and create its own CImageDecoder there.

One final point about threads relates to decoding from descriptors. Threaded decoders use a mechanism that guarantees mutual exclusion on the descriptor without requiring locks. However, one assumption is made, that only the parent thread will write to the descriptor. To ensure the integrity of the descriptor, the calling application should only ever update the descriptor from the parent thread, as the application has no way of determining whether a decoder object has requested a thread for itself.

[Top]


MIME type and plugin reporting

CImageDecoder can retrieve the MIME-type associated with a particular image stored either in a file with GetMimeTypeFileL() or a descriptor with GetMimeTypeDataL().

static void GetMimeTypeFileL(RFs& aFs, const TDesC& aFileName, TDes8& aMimeType);

static void GetMimeTypeDataL(const TDesC8& aImageData, TDes8& aMimeType);

Note: The GetMimeTypeFileL() and GetMimeTypeDataL() calls are both static - a decoder object does not need to exist for them to be used.

Both CImageDecoder and CImageEncoder include facilities to report the image formats that are supported on a specific system, determined from the plugins that are installed.

static void GetImageTypesL(RImageTypeDescriptionArray& aImageTypeArray);

static void GetImageSubTypesL(const TUid aImageType, RImageTypeDescriptionArray& aSubTypeArray);

static void GetFileTypesL(RFileExtensionMIMETypeArray& aFileExtensionArray);

static CImplementationInformationType* GetImplementationInformationL(TUid aImplementationUid)

Note: The above calls are all static and as such a decoder object does not need to exist for them to be used.

[Top]


Extended decoders/encoders

Some plugin writers may choose to provide a decoder object that is actually a derivative of CImageDecoder, rather than a CImageDecoder itself, or the equivalent for encoders. Although such objects are always usable normally, it gives the ability to provide additional calls to the interface - perhaps simplifying access to additional data chunks or even different conversion functions. In order to utilise this, the additional class must be implemented in an extra DLL that is linked to by both the plugin and the calling program (it is not possible to normally link to an ECom plugin). The calling code should check that the plugin is the one expected using ImplementationUid() before continuing. The particular details of additional features will depend on the plugin itself.

Note: This feature is intended for use in applications such as photo or image editors that typically work with a limited set of plugins, rather than browsers that use a limited feature set but use as many plugins as possible. This is important, because the shared DLL is linked to in a static way by the calling program, and must thus be present for the calling program to even load. If it is necessary for this shared DLL to be optional, then the calling DLL must itself be dynamically linked to the main application.

[Top]


Memory usage

The complete conversion operation (for decoding and encoding) uses the calling thread's heap. The client has to ensure that enough space is available on the heap; this is especially important for applications that can open a large number of images, such as web-browsers.

[Top]


Error Handling

All error conditions in synchronous calls result in leaves and all asynchronous errors are returned using via TRequestStatus. In addition to KErrCorrupt (the plugin could not interpret the image data) and KErrUnderflow (additional data is needed to complete the conversion) any of the standard OS error conditions such as KErrNoMemory and KErrNotFound can also occur and should be handled appropriately by the client.

[Top]


Performance

All conversion operations make extensive use of background active objects, which differ significantly from threaded processing regarding concurrency and latency. For real-time processing use threads as opposed to background active objects.

[Top]


See also