Building custom widgets with the Zinzala SDK - page 3

Once we have got the file extension in the variable lExt, we can call the Photon function PiIoGetHandlerByExt() to give us the handler that will be used to load the image. If the file format is not supported lHandler will be set to NULL. Photon currently provides only handlers for GIF, JPEG, BMP and PNG.

memset(&lInfo,NULL,sizeof(PiLoadInfo_t)); lInfo.flags = Pi_IO_SHMEM; lInfo.shmem_threshold = 100; lInfo.handler = lHandler; lInfo.filename = aFilename; // load the image lImage = PiLoadImage(&lInfo);

PiLoadImage() loads the image from the file into a Photon image structure PhImage_t. A structure of type PiLoadInfo_t is used as an argument to pass all the required information to the function, such as the filename and the handler to be used. The flag Pi_IO_SHMEM indicates that the image to be created should use shared memory, if its size is above a given threshold. Using shared memory for the image data, which are rows of pixels, is a nice idea when the bitmap is to be displayed. The Photon server will access the image's data in the shared memory when it is draw, instead of having the application send it. This is not really required since we will not be displaying the image.

if(lImage) { cBitmap* lBitmap; // create a cBitmap and return it lBitmap = new cBitmap(lImage); if(!cBitmap::VerifyD(lBitmap)) return lBitmap; else return NULL; } else return NULL;

If the image was successfully loaded into lImage, we can use it to create a cBitmap object. The static method VerifyD() checks the validity of the object. If the object has been allocated and is invalid, it will be deleted by that method. Otherwise, the method will return kErrNone. Since the cBitmap assume ownership of the Photon image, we don't need to delete it.

} else return NULL; } else return NULL; }
From cBitmap to resource

Earlier, we decided that all the graphics are going to be stored as resources in a shared object. For that reason, we need to store all the required information in a C++ file. The following type will provide everything we need to instantiate a cBitmap object:

typedef struct tBitmapResource { tUint32 iWidth; // width of the bitmap tUint32 iHeight; // height of the bitmap tUint32 iIndex; // index of the transparent color in the palette tUint16 iColors; // number of color in the palette tUint32 iLength; // length in bytes of the bitmap's data tUint8* iBits; // bitmap's data tUint32* iPalette; // palette of colors } tBitmapResource;

Here's the function that will output a bitmap into a C++ compilable form:

void DumpBitmapToFile(cFile &aHeader,cFile &aCode,cBitmap *aBitmap,tColor *aPalette, tUint16 aColors,const char *aName) { tUint16 lWidth,lHeight; tUint8 lIndex; tUint32 lLength; tUint8* lBits; PgColor_t lColor; aBitmap->GetTransparent(lIndex); aBitmap->GetSize(lWidth,lHeight); lLength = aBitmap->BitsLength(); lBits = aBitmap->GetBits();

First, we retrieve the size, transparency and pixel data from aBitmap. The local variable lLength will contain the length of the data in bytes.

aHeader.Write("extern const tBitmapResource kRscBitmap%s;\n\n",aName);

aHeader is a reference to the cFile object pointing to the C++ header file. Here, we define a constant of type tBitmapResource for the bitmap we are currently outputting.

aCode.Write("tUint8 kBitmap%sBits [] = {\n\n\t",aName); for(tUint16 k=0;k<lLength;k++) { lIndex = lBits[k]; if(k + 1 == lLength) aCode.Write("0x%02x",lIndex); else aCode.Write("0x%02x,",lIndex); if(!((1+k) % 16)) aCode.Write("\n\t"); } aCode.Write("};\n\n");

Writing each pixel index color is fairly easy. Just as a reminder, we are using palette-based graphics. We simply loop over all the pixels and write their hexadecimal value. For better legibility, we output these values into lines 16 pixels wide.

aCode.Write("tUint32 kBitmap%sPalette[%d] = {\n\n\t",aName,aColors); for(tUint16 i=0;i<aColors;i++) { lColor = PgARGB(aPalette[i].iAlpha,aPalette[i].iRed,aPalette[i].iGreen, aPalette[i].iBlue); aCode.Write("0x%06x,",(tUint32)lColor); if(!((1+i) % 8)) aCode.Write("\n\t"); }

Outputting the palette of color used by the bitmap is not very complicated. However, there is a little trick to know. If we write the RGB color in the form of an unsigned 32 bit integer, we can use them directly when instantiating the bitmap. By using the Photon macro PgARGB(), we insure that the color will be coded in a format that can be directly understood by the underlying Photon. To improve the legibility of the C++ file, we will also output only 8 colors per lines.

aCode.Write("\n};\n\n"); aCode.Write("const tBitmapResource kRscBitmap%s\t= {\n",aName); aCode.Write("\t%d,%d,0x%02x,%d,%d,kBitmap%sBits,kBitmap%sPalette\n};\n",lWidth, lHeight,lIndex,aColors,lLength,aName,aName); }

Last but not least, in the C++ file we declare the same constant that we have previously defined in the header file. This time, we fill in all the data specifics to the bitmap.

Now, how will it look like in the C++ file ?

tUint8 kBitmapStopDBits [] = { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, ... ... ... 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03, 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; tUint32 kBitmapStopDPalette[4] = { 0x88c188,0x82bd82,0x77b577,0x6bad6b, }; const tBitmapResource kRscBitmapStopD = { 25,25,0x02,4,800,kBitmapStopDBits,kBitmapStopDPalette };

Print version

All content © 2004-2007, hexaZen - Vancouver BC, Canada