Bitmaps |
|
Bitmaps Fundamentals |
Introduction |
A bitmap is a graphic object used to display a picture on a window or to store it in the computer memory as a file. It is the primary type of graphics used for various occasions. For example, a bitmap can be used as a background for a window. That is the case for the Pinball game that ships with some versions of Microsoft Windows: |
A bitmap can also be used for aesthetic purposes to decorate a dialog box. That’s how it is used on some of the installation wizard boxes such as the graphic on the left section of the WordPerfect 2002 installer: Probably the most regular use of bitmaps is as small graphics on toolbars: There are three main ways you create or add a bitmap to your application. You can create an array of byte values that describe the bitmap. You can design a bitmap using a low-level bitmap application like Image Editor, or you can use a professional picture.
There are three types of bitmaps we will be creating for our lessons. The simplest consists of designing a regular picture made of regular colors from the Image Editor. Another technique consists of declaring an array of bits that describes the bitmap; then translate this array into a handle to bitmap before actually using it. The last technique, which requires some design or importing, consists of using a more advance picture in an application. Creating a bitmap and making it available to an application is just one aspect. The goal is to use such a bitmap or to decide what to use it for. Normally, the way you create a bitmap has some influence on where and how that bitmap is used. For example, bitmaps created in Image Editor using only its tools are appropriate to display on top of controls that need small bitmaps. Those bitmaps and those created from an array of bits are also the prime candidates to use as drawing brushes. Bitmaps that are professional looking pictures and that tend to be taller or wider are usually used to display illustrative pictures. In reality, any of the bitmaps can be used in any scenario of your choice.
Image Editor provides a good environment to create small bitmaps that would be used on controls that need them. Such bitmaps usually have a size of 16x16 pixels, 32x32 pixels, or a ratio of width and height appropriate for the control that needs the bitmap. We will use bitmaps on bitmap buttons, toolbars, and list-based controls, etc. To create a bitmap, on the main menu of Image Editor, you would click File -> New -> Bitmap File (.bmp). A dialog box would come up. This allows you to specify the possible dimensions of the picture. You can specify the dimensions of your choice according to the intended eventual use of the bitmap. You can also get a bitmap by changing an existing picture. To modify an existing picture, you can use any graphics software that is fit. Windows Paint that ships with the operating system is a good cheap alternative to commercial applications. Jasc Paint Shop Pro is also an excellent product suitable to do almost anything with a bitmap. To manipulate a bitmap with such applications, you should first import it. On the main menu of Windows Paint, you can click File -> Open… Change the Files of Type to the kind of file you want to open, or set it to All Files. Locate the desired file and click Open. Alternatively, you can find a way to copy the graphic and paste it into Windows Paint. After designing your bitmap, you must save it. A bitmap is a Windows file that has an extension of .bmp
Paint (or PaintBrush) is an application that gets installed with Microsoft Windows. It provides a cheap solution to creating or maipulating bitmaps. It is a little more flexible than Image Editor. For example, if you try opening a color-intensive picture in Image Editor, you would receive an error:
The same picture can be opened in Paint:
Of course an alternative is to open the picture in another application such as Paint, select then copy it to the clipboard, and then paste it in Image Editor. One of the differences between both applications is that when creating a new bitmap in Image Editor, you must specify its size. After doing this, if you paste an image that is wider or taller than the allocated rectangle, part of the picture would not appear. You would then have to resize the rectangle and paste again. In Paint, if you attempt to paste an image that is wider and/or taller than the primarily allocated rectangle, you would be asked whether you want the rectangle to be resized to accommodate the picture. Based on this review, if you are creating a bitmap that would be displayed on top of Windows controls that need small pictures (bitmap buttons, list view, tree view, etc) use Image Editor to prepare them. If you are preparing an advanced picture to use in your application, you should use either Paint or a more advanced graphic editor. C++ Builder does not care where or how you created a bitmap as long as it is in the right format (either bmp, jpeg, or jpg extension).
The VCL provides support for bitmaps through the TBitmap class from the Graphics namespace. Some classes, such as TBrush, already have a Bitmap member variable that you can use initialize appropriately. In most cases, you will need to declare a pointer to TBitmap. To do this, you must precede the name of the class with the Graphics namespace. Here is an example: //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { Graphics::TBitmap *LaCourt = new Graphics::TBitmap; } //--------------------------------------------------------------------------- Like all other dynamic objects, after using the bitmap, you should delete it. If you declare it locally, you can also delete it in the same event or method. Here is an example: //--------------------------------------------------------------------------- void __fastcall TForm1::FormDblClick(TObject *Sender) { Graphics::TBitmap *BmpMercedes = new Graphics::TBitmap; try { // Treat the bitmap file here } __finally { // Time to delete the pointer delete BmpMercedes; } } //--------------------------------------------------------------------------- If you declare it globally, make sure you delete it when the application is destroyed. After declaring the variable, you must initialize it appropriately before actually using it.
Once the file is ready, you can use it in your application. For example, you can display it on a form. Because the form is equipped with a canvas, to display a picture, you can call the TCanvas::Draw() method. Its syntax is: void __fastcall Draw(int X, int Y, TGraphic* Graphic); The X and Y values specify the corner from where to start drawing. Normally, it will be the top-left coordinates of the picture. The Graphic parameter is the graphic file to draw on the canvas. This would be done as follows: //--------------------------------------------------------------------------- void __fastcall TForm1::FormDblClick(TObject *Sender) { Graphics::TBitmap *BmpMercedes = new Graphics::TBitmap; try { Canvas->Draw(10, 10, BmpMercedes); } __finally { delete BmpMercedes; } } //---------------------------------------------------------------------------
In order to use a bitmap in your application, you must import it from its file to the application. The easiest way to do this consists of calling the TGraphic::LoadFromFile() method. Its syntax is: virtual void __fastcall LoadFromFile(const AnsiString FileName); This method is particularly easy to use as long as you know the location of the bitmap file. If the picture is in the same directory as the current project, you can simply type its name and its extension as a string and pass it as argument. An example would be: //--------------------------------------------------------------------------- void __fastcall TForm1::FormDblClick(TObject *Sender) { Graphics::TBitmap *BmpMercedes = new Graphics::TBitmap; try { BmpMercedes->LoadFromFile("Mercedes2.bmp"); Canvas->Draw(10, 10, BmpMercedes); } __finally { delete BmpMercedes; } } //--------------------------------------------------------------------------- If the file is not in the same directory as the project, you may have to specify its complete path. Here is an example: //--------------------------------------------------------------------------- void __fastcall TForm1::FormDblClick(TObject *Sender) { Graphics::TBitmap *BmpMercedes = new Graphics::TBitmap; try { BmpMercedes->LoadFromFile("C:\\Programs\\Mercedes1.bmp"); Canvas->Draw(10, 10, BmpMercedes); } __finally { delete BmpMercedes; } } //--------------------------------------------------------------------------- If the file, its path, and its extension are correct, the file can be used:
If the file does not exist when you try accessing it, in other words, if the file or the path you specified is not valid (the file and the path are not checked at compilation time, they are checked when the application is asked to retrieve the bitmap), you would receive an error:
As you can see, the exception thrown is of type EFOpenError (which stands for Exception-File-Open-Error), meaning that the information given about opening the file is incorrect somewhere. You can display our own message as follows:
Another technique you can use to open a bitmap consists of retrieving it from a resource file. Before doing this, you must have a resource file with .res extension. You can directly create a resource file from Image Editor but once again, you would have to deal with that application’s limitations. Alternatively, you can first create a Windows resource file that has the .rc extension and create a header file that lists its resources. The header file is used to specify a constant number for each resource. For this example, the header file can be named resource.h. In the file, a constant can be defined as follows: #define DEUXFILES 1000 After creating the header file, you can create a resource file, which is simply a text file with an extension of .rc and, in the file, each resource can be specified using the name of the constant created in the header file. A bitmap resource can be created as follows: #include "resource.h" DEUXFILLES BITMAP "Filles.bmp"
After creating the resource file, you must import it into your project. This is done by click Project -> Add to Project… from the main menu, selecting the rc file and clicking Open. After adding the resource file, you should compile it to produce a
.res file. This makes your file ready. void __fastcall LoadFromResourceName(unsigned Instance, const AnsiString ResName); The easiest way to do this is to create the resource file in the same directory as the project that is using it. This is because the LoadFromResourceName() method requires the instance of the executable file that contains the resource file. If it is located in the same folder, you can simply pass the instance of the current project as the Instance argument. The second parameter, ResName, is the name of the bitmap to be loaded. Normally, it should be the identifier of the bitmap as defined in the header file. Here is an example:
One more alternative you have into preparing a picture to display in your application consists of using an identifier from a resource file. Since the steps are exactly the same as those used above, we will follow them in a Practical Learning session.
In most circumstances, in order to use a bitmap, you will need to declare a pointer to TBitmap. Because the TBitmap class has only a default constructor, after declaring the pointer, you will need to load a bitmap into it before using it. Once the variable contains a bitmap, you can use it as you see fit. If there is no bitmap stored into it and you attempt to use it, you may receive an error or an unreliable result. If you want to check first whether the variable contains a bitmap, you can check its Empty Boolean value. If the variable contains a bitmap, this property would be true. Otherwise, it would be false. Once a bitmap has been loaded, as a visible object, it has dimensions represented by a width and a height. These are its Width and its Height properties. You can either retrieve these values or change them.
A bitmap uses a set of colors known as its palette. To get or set the characteristics of these colors, you can access the Palette property of the TBitmap variable. virtual void __fastcall Assign(Classes::TPersistent* Source); The Source parameter is the variable that holds the bitmap you want to copy and will be assigned to the variable that is making the call.
A pattern brush is one that uses a bitmap instead of a plain color like the solid brush. Therefore, to use a pattern brush, you must first create a bitmap. There are two main options to do this. You can first load a bitmap from a file as we have done so far. Once the bitmap is ready, assign its pointer to the Bitmap property of the Brush member variable of the TCanvas class you are using. Alternatively, to create a pattern brush, you can declare and initialize an array of BYTE values that describe the bitmap.
The primary means of using a bitmap in your application is obviously through the TBitmap class with its properties and methods. If the VCL does not natively provide the bitmap functionality you are using for, you can use one of the Win32 functions. The Win32 library supports bitmaps through various functions. Most of these functions return a handle to BITMAP, implemented as HBITMAP. To use the return value of one of these, the TBitmap class provides a Handle member variable particularly easy to use, just all Handle member variables provided by the TWinControl class to its children. Therefore, anything you would have done on the HBITMAP handle, to use it in your application, simply assign its variable to the TCanvas::Handle and it is made ready. A bitmap, like any other GDI object, must be created first, either as a resource file or by definition. Once it exists, before using it, it must be selected into a device context. Fortunately, the device context is already largely implemented in VCL objects through the TCanvas class that is made a member variable of all classes that need a device context.
The most basic bitmap is created from an array of constant values that describe the bitmap. This type is created using the CreateBitmap() function. Its syntax is: HBITMAP CreateBitmap(int nWidth, int nHeight, UINT cPlanes, UINT cBitsPerPel, CONST VOID *lpvBits);
The nWidth and nHeight parameters specify the dimensions of the bitmap, in pixels. The
cPlanes parameter holds the number of color planes used by the device. The
cBitsPerPel parameter is an array of color values. Here is an example: //--------------------------------------------------------------------------- void __fastcall TForm1::FormPaint(TObject *Sender) { HBITMAP HBmp; WORD wBits[] = { 0x00, 0x22, 0x44, 0x88, 0x00, 0x22, 0x44, 0x88, 0x22, 0x44, 0x88, 0x00, 0x22, 0x44, 0x88, 0x00, 0x44, 0x88, 0x00, 0x22, 0x44, 0x88, 0x00, 0x22, 0x88, 0x00, 0x22, 0x44, 0x88, 0x00, 0x22, 0x44 }; HBmp = CreateBitmap(32, 32, 1, 1, wBits); HBRUSH hBrush = CreatePatternBrush(HBmp); Canvas->Brush->Handle = hBrush; Canvas->Rectangle(20, 20, 400, 400); } //---------------------------------------------------------------------------
|
Home | Copyright © 2005-20007 FunctionX, Inc. | |