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.
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:
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.
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.
The decoder/encoder plugin itself uses thread(s).
The calling application requests that a new thread be used for a decode/encode plugin.
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:
There are extra overheads associated with threads, and the required inter-thread communication mechanism will almost certainly increase the memory requirements and overall decode/encode times - albeit in a relatively minor way.
Active objects are not pre-emptive and so even the best written background active object can effectively freeze the application for short periods as it performs calculations.
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.
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.
The GetImageTypesL()
calls of CImageDecoder
and CImageEncoder
both return lists of primary supported formats. This list is in the format of description, image type and image sub-type
where image sub-type is always KNullUid
.
The GetImageSubTypesL()
calls of CImageDecoder
and CImageEncoder
both return lists of supported sub-formats. This list is in the format of description, image type and image sub-type.
The GetFileTypesL()
calls of CImageDecoder
and CImageEncoder
both return lists of supported file extensions and primary MIME types.
CImageDecoder::GetImplementationInformationL()
returns the ECom implementation information for a specific plugin. For more information see CImplementationInformation
.
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.
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.
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.
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.
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.
ICL client side architecture - brief overview of the architecture of the image converted library client side classes.
Overview - general overview of ICL, synchronous and asynchronous methods, active objects and concurrency issues.
Image decoding - frame information and data, still image decoding, animated image decoding, progressive decoding and buffered decoding.
Image encoding - encoding/decoding feature comparison, image encoding.
Additional information - dithering, enabling progressive decoding, MIME type and plugin reporting, threading, memory usage, error handling and performance considerations.