Symbian
Symbian OS Library

SYMBIAN OS V9.3

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



Image Decoding

The image decoding class CImageDecoder (CBufferedImageDecoder is described later) provides functions to decode images held in descriptors or files from standard formats for use with devices such as screens, browsers and viewer applications. This class provides these features via a plugin framework. The standard formats supported by the decoder plugins are shown in the table in Overview.

For the purposes of this description, the decoding process has been broken down into the following sections:


Creation

CImageDecoder decodes images stored in files or in descriptors. The decoder object is owned by the client and must be deleted once decoding is finished. CImageDecoder objects cannot be reused to decode other images - each image requires its own instance of the decoder.

CImageDecoder objects are created using the CImageDecoder::DataNewL() and CImageDecoder::FileNewL() factory functions for images held in descriptors or files respectively:

In creating a CImageDecoder object, a suitable plugin has to be associated with the image to be decoded. How the plugin is specified depends on the factory function you use to create the object and what parameters you specify. There are four alternatives:

It is possible for more than one valid plugin decoder to be available for a specific image format. If a plugin determined by MIME type or type/sub-type fails to open an image due to KErrCorrupt, it will continue to try with subsequent valid plugins if available. This mechanism is carried out behind the scenes and is largely invisible to the application. If you require a specific function you know to be available within a specific plugin, specify that plugin using aDecoderUid.

[Top]


Conversion

As part of the CImageDecoder creation basic information about the image is pre-read from the image headers. This information is used to support certain enquiry methods such as CImageDecoder::FrameCount() and CImageDecoder::FrameInfo() and so on (more on the enquiry methods is supplied in Enquiry features).

You are free to decode any subset of individual frames, in any order, and to repeat the decoding if necessary. To decode an image frame use the asynchronous conversion method CImageDecoder::Convert(), as shown below.

void Convert(TRequestStatus* aRequestStatus, CFbsBitmap& aDestination, TInt aFrameNumber = 0);

void ContinueConvert(TRequestStatus* aRequestStatus);

Note: The use of CImageDecoder::ContinueConvert() is described in Streamed and progressive decoding.

Bitmap masks

There is a second variant of the Convert() function intended for use when decoding images with bitmap masks.

void Convert(TRequestStatus* aRequestStatus, CFbsBitmap& aDestination, CFbsBitmap& aDestinationMask, TInt aFrameNumber = 0);

Within the Symbian OS it is normal to store the bitmap mask separately from the main image data. Calls such as BitBltMasked() expect this data to be provided separately. This separation is true for both CFbsBitmap objects and MBM files.

To determine whether an image contains a bitmap mask use FrameInfo(), the presence or absence of a mask will be indicated the ETransparencyPossible flag. Two types of mask are possible.

Note: Images that contain bitmap masks do not have to have those masks decoded if they are not required.

Scaling and display modes

Before Convert() can be used the destination CFbsBitmap objects for image data and possibly bitmap masks must be created. The simplest way to do this is to use a 1 to 1 approach, that is, create the CFbsBitmap object with the same properties as the source image (if at all possible). This could be achieved by using something similar to:

iFrameInfo = &imageDecoder->FrameInfo(FrameNum);

iBitmap->Create(iFrameInfo->iOverallSizeInPixels, iFrameInfo->iFrameDisplayMode );

If the ECanDither flag of CImageDecoder::FrameInfo() iFlags is set then the destination display mode can be adjusted. In such cases it is generally recommended that the current window's display mode is used as this can make drawing faster.

Note: The mask bitmap must have the same size in pixels as the main image, even though the display mode is generally different.

As indicated above the size of the image bitmap is available via FrameInfo() (iOverallSizeInPixels). However, in addition to a direct mapping of an image's size, ReducedSize() function can be used to calculate the reduced size of the decoded bitmap based on the input parameters.

If the EFullyScaleable flag of FrameInfo() iFlags is set, you can specify any size for the CFbsBitmap and the image will be resized appropriately.

Animations

Included in the CImageDecoder::FrameInfo() result are flags that enable the support of GIF animation. These flags are iDelay, ELeaveInPlace, ERestoreToBackground and ERestoreToPrevious. ICL provides these flags to enable the application to implement the animation; ICL does not provide functions to display the animation directly.

Processing the information from these flags will inevitably require a state machine, and additional timers, within the application. Requirements will vary depending on the architecture of the client application itself.

Background colours

Some image formats contain background colour information. This is information is presented by ICL via CImageDecoder::FrameInfo() iBackgroundColor. If a non-masked image with background colour is decoded, the colour is included in the image data. If the decoded image also contains a bitmap mask, then the background colour will be a component of the mask CFbsBitmap object. Depending on your application, you may want to choose your own background colour rather than use the one provided by the source image.

[Top]


Enquiry features

Previous sections shown above have made use of CImageDecode::FrameInfo(). There are however, other enquiry functions that also provide useful information. They are:

[Top]


Streamed and progressive decoding

CImageDecoder includes facilities to support the simultaneous decoding and display of images as they are being loaded. The decoder does not wait for the entire image to be loaded before processing it, rather it begins as soon as possible, stops when it runs out of data and then carries on when more data is available. The decoding rules that CImageDecoder follows are shown below:

There is no explicit decoder call to say "all of the data is now present". This could be done via inference, continuously checking IsHeaderProcessingComplete() until it returns ETrue. However, this is not advisable as it is possible that IsHeaderProcessingComplete() could continue to return EFalse even after the application has finished sending image data. Your state machine should be written so that it takes this possibility into account.

[Top]


Buffered decoding

CBufferedImageDecoder is a wrapper that encapsulates not only a CImageDecoder but also the descriptor used to store the image, and in some circumstances can replace the use of CImageDecoder itself. CBufferedImageDecoder can always be created, even if there is no data available at the time of creation. Another key feature of CBufferedImageDecoder is that it can be reused to decode multiple images. The use of this class is outlined below.

[Top]


See also