|
Programming with wxBitmapThese are some of the things you can do with a wxBitmap:
On some platforms (in particular, Windows), the bitmap is a limited resource, so if you have many images to store in memory, you may prefer to work mainly with wxImage objects and convert to a temporary wxBitmap when drawing on a device context. Before discussing how to create wxBitmap and draw with it, let's summarize the main functions (Table 10-2).
Creating a wxBitmapThere are several ways to create a wxBitmap object. You can create the object in an uninitialized state (no bitmap data) by using the default constructor. You will need to call Create or LoadFile or assign another bitmap to it to do anything useful with the object. You can create a wxBitmap with a given size and depth. The bitmap will be filled with random data, so for this object to be useful, you will need to draw on it. The following code creates a 200 x 100 pixel bitmap and gives it a white background. // Create a 200x100 bitmap with the current display depth wxBitmap bitmap(200, 100, -1); // Create a memory device context wxMemoryDC dc; // Select the bitmap into the DC dc.SelectObject(bitmap); // Set the background dc.SetBackground(*wxWHITE_BRUSH); // Color the bitmap white dc.Clear(); // Select the bitmap out of the DC dc.SelectObject(wxNullBitmap); You can create a bitmap from an image object, preserving any mask or alpha channel in the original image: // Load an image wxImage image(wxT("image.png"), wxBITMAP_TYPE_PNG); // Convert it to a bitmap wxBitmap bitmap(image); A bitmap can also be constructed from an icon by using CopyFromIcon: // Load an icon wxIcon icon(wxT("image.xpm"), wxBITMAP_TYPE_XPM); // Convert it to a bitmap wxBitmap bitmap; bitmap.CopyFromIcon(icon); Or you can load a bitmap from a file: // Load from a file wxBitmap bitmap(wxT("picture.png", wxBITMAP_TYPE_PNG); if (!bitmap.Ok()) { wxMessageBox(wxT("Sorry, could not load file.")); } wxBitmap can load all the file types that wxImage can (see Table 10-7), by using either wxImage or a more efficient platform-specific implementation for certain file types. Some of the most popular formats are PNG, JPEG, TIFF, BMP, and XPM, which are available on all platforms for both loading and saving, assuming that wxWidgets support for these formats has been enabled.
On Mac OS X, a PICT resource can also be loaded by specifying wxBITMAP_TYPE_PICT_RESOURCE. If you want to load a bitmap from a platform-dependent source, you can use the wxBITMAP macro. For example: #if !defined(__WXMSW__) && !defined(__WXPM__) #include "picture.xpm" #endif wxBitmap bitmap(wxBITMAP(picture)); This will load the resource named picture from the executable on Windows and OS/2, and on all other platforms, it will load an XPM from the picture_xpm variable. However, the XPM format is supported on all platforms, so use of this macro is not usually necessary. Setting a wxMaskEach wxBitmap object can contain a wxMask, a monochrome bitmap that indicates the transparent areas of the main bitmap. This will be created automatically when you load a transparent image, for example using XPM, PNG, or GIF, but you can also create it programmatically and assign it to a bitmap with SetMask. You can create a wxMask object from a wxBitmap, or a wxBitmap plus a color to indicate the transparent area. The following example creates a monochrome transparent image called mainBitmap, 32 pixels wide by 32 pixels high, from bitmap data (imageBits) and a mask (maskBits) where 1 is black and 0 is white for the bits, and 1 is opaque and 0 is transparent for the mask. static char imageBits[] = { 255, 255, 255, 255, 31, 255, 255, 255, 31, 255, 255, 255, 31, 255, 255, 255, 31, 255, 255, 255, 31, 255, 255, 255, 31, 255, 255, 255, 31, 255, 255, 255, 31, 255, 255, 255, 25, 243, 255, 255, 19, 249, 255, 255, 7, 252, 255, 255, 15, 254, 255, 255, 31, 255, 255, 255, 191, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }; static char maskBits[] = { 240, 1, 0, 0, 240, 1, 0, 0, 240, 1, 0, 0, 240, 1, 0, 0, 240, 1, 0, 0, 240, 1, 0, 0, 240, 1, 0, 0, 240, 1, 0, 0, 255, 31, 0, 0, 255, 31, 0, 0, 254, 15, 0, 0, 252, 7, 0, 0, 248, 3, 0, 0, 240, 1, 0, 0, 224, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; wxBitmap mainBitmap(imageBits, 32, 32); wxBitmap maskBitmap(maskBits, 32, 32); mainBitmap.SetMask(new wxMask(maskBitmap)); The XPM FormatWhere small bitmaps with transparency are needed, for example as toolbar buttons or bitmaps in notebooks and tree controls, wxWidgets programmers often use XPM. One advantage of this format is that it uses C/C++ syntax, and it can either be loaded dynamically or compiled into your program. Here's an example. // You can also use #include "open.xpm" static char *open_xpm[] = { /* columns rows colors chars-per-pixel */ "16 15 5 1", " c None", ". c Black", "X c Yellow", "o c Gray100", "O c #bfbf00", /* pixels */ " ", " ... ", " . . .", " ..", " ... ...", " .XoX....... ", " .oXoXoXoXo. ", " .XoXoXoXoX. ", " .oXoX..........", " .XoX.OOOOOOOOO.", " .oo.OOOOOOOOO. ", " .X.OOOOOOOOO. ", " ..OOOOOOOOO. ", " ........... ", " " }; wxBitmap bitmap(open_xpm); As you can see, XPMs are encoded using character data. Before the image data, there is a palette section that maps each character to its color, either as an identifier or as a hash-prefixed six-digit hexadecimal string. Using the identifier None causes this character to represent the transparent area in the bitmap. Although XPM support is uncommon among Windows image manipulation programs, you can create images as PNGs and convert to XPM using a tool such as ImageBlocks (bundled with DialogBlocks), or you can simply write your own converter using wxWidgets. Drawing with BitmapsYou can draw with a bitmap in a couple different ways. You can associate it with a memory device context (wxMemoryDC) and then use wxDC::Blit to transfer the contents of the bitmap to another device context. Or, you can use the simpler wxDC::DrawBitmap. In either case, if the bitmap is transparent or has an alpha channel, you can specify transparent drawing by passing true to the function. The two methods are illustrated in the following. // Draw a bitmap using a wxMemoryDC wxMemoryDC memDC; memDC.SelectObject(bitmap); // Draw the bitmap at 100, 100 on the destination DC destDC.Blit(100, 100, // Draw at (100, 100) bitmap.GetWidth(), bitmap.GetHeight(), // Draw full bitmap & memDC, // Draw from memDC 0, 0, // Draw from bitmap origin wxCOPY, // Logical operation true); // Take mask into account memDC.SelectObject(wxNullBitmap); // Alternative method: use DrawBitmap destDC.DrawBitmap(bitmap, 100, 100, true); Chapter 5, "Drawing and Printing," discusses drawing with bitmaps in more detail. Packaging Bitmap ResourcesIf you come from a Windows programming background, you are accustomed to loading bitmaps from the resource section of the executable. You can still do this by passing a resource name and the wxBITMAP_TYPE_BMP_RESOURCE type to the constructor, but you are likely to want a less platform-specific method. A portable way to package resources, whether they are bitmaps, HTML files, or other files required by an application, is to store them in a single zip file alongside the executable or in a separate data folder. Then you can use the virtual file system functionality in wxWidgets to load the image directly from the zip file, as the following fragment shows. // Create a new file system object wxFileSystem*fileSystem = new wxFileSystem; wxString archiveURL(wxT("myapp.bin")); wxString filename(wxT("myimage.png")); wxBitmapType bitmapType = wxBITMAP_TYPE_PNG; // Create a URL wxString combinedURL(archiveURL + wxString(wxT("#zip:")) + filename); wxImage image; wxBitmap bitmap; // Open the file in the archive wxFSFile* file = fileSystem->OpenFile(combinedURL); if (file) { wxInputStream* stream = file->GetStream(); // Load and convert to a bitmap if (image.LoadFile(* stream, bitmapType)) bitmap = wxBitmap(image); delete file; } delete fileSystem; if (bitmap.Ok()) { ... } For more information about virtual file systems, please see Chapter 14, "Files and Streams." |
|