Wednesday, September 2, 2009

Qt for S60 Still Bogged Down By Symbian

Qt for S60 has brought the simplicity and power of Qt to Symbian phones, but there are still a few corner cases which are hurting, and one of those is the camera, whose code is still heavily tied to old Symbian cruft.

Symbian's code for cameras returns captured images as CFbsBitmaps. Don't even begin to guess what CFbs stands for, you'll just end up crying "why, why!?" Luckily Qt for S60 provides a function which converts CFbsBitmaps to QPixmaps, but it seems that the image capture is faulty, even though if at any point you take an image from the viewfinder and convert it it turns out fine.

So I decided to debug to see if the CFbsBitmap returned from the camera's viewfinder on capture was the source of the problems, and not Qt's conversion function.

After an hour or so of Googling (tm) and messing around in the Nokia forums in dead ends, I've found this wonderful snippet of code to save the CFbsBitmap to a file to see if that's the case (http://discussion.forum.nokia.com/forum/showthread.php?p=636992). (Note: CFbsBitmap's Save() function merely saves the binary CFbsBitmap to a file, unopenable by anybody other than Symbian, and thus useless):

------------------------------------------------

_LIT(KFileName, "c:\\1.bmp");
_LIT8(KMime, "image/bmp");
RFs& fs = CEikonEnv::Static()->FsSession();
CImageEncoder* encoder = CImageEncoder::FileNewL(fs, KFileName(), KMime(), CImageEncoder::EOptionAlwaysThread);
TRequestStatus status = KRequestPending;
encoder->Convert(&status, *bitmap);
User::WaitForRequest(status);
delete encoder;
User::LeaveIfError(status.Int());

------------------------------------------------

Let's break this monster down:
· _LIT8 is one of Symbian's ass-backwards ways of declaring a "string" for example a string called KMimeType with value "image/bmp"
· RFs is a file session, which is basically a guy that manages accesses to files, and here we pull out the manager for the application using CEikonEnv (again, don't ask)
· Then we create an encoder to change the CFbsBitmap into a real bitmap and save it to a file with the rest of this wonderful piece of code

The Qt equivalent of this is:

QPixmap *pix:
pix.save( "somewhere.format" );

Why was this so hard to program into Symbian!? If you're going to put a function to save the raw binary of a CFbsBitmap to a file, why not a truly encoded one?

Every day I code in Symbian, I feel a piece of my logical mind get torn to pieces.

3 comments:

Stecchino said...

love the way you have dissected Symbian code into nice digestible chunks of pure horror.
Thanks

And perhaps a troll/nokian will answer if the camera stuff will be part of QtMobility. Yes, I know the namespace doesn't suggest it will.

Blackpaw said...

Ah yes, the horror that is the Symbian SDK - more classes than windows MFC. Static casting several levels backup a heirachy to add items to a list box ... the horror, the horror.

I actually ended up coding our app in Python rather than hack my way through mess. Can't wait until QtMobility is commercially usable.

Shane said...

You are probably getting a YUV bitmap from the camera.
This helps with performance, because the normal thing to do with a captured image is save it as a JPEG.
The useless conversion to/from RGB is eliminated in this case.

The bitmap save function only saves in the native format - this is the same on WIN32 (only supports BMP), and X (only supports X11). You need to use a library to support other file formats.

btw, Qt doesn't support YUV bitmaps, the to/from CFbsBitmap functions only support formats that are common (at the moment)

They are equivalent to the to/from HBITMAP functions on the win32 port.