Software Solution for Engineers and Scientist Episode 9 potx

90 341 0
Software Solution for Engineers and Scientist Episode 9 potx

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

HBITMAP SelectBitmap (HDC, HBITMAP); | || 12 The first parameter must be the handle of a memory device context. The sec - ond parameter is the handle to the bitmap being installed. If the call succeeds, the macro returns the handle to the device context object being replaced. If the call fails, it returns NULL. Using the SelectBitmap() macro instead of the SelectObject() function produces code that is correct and the coding is made eas - ier. Recall that programs that use the object selection macros must include the windowsx.h file. The handle to the bitmap used in the SelectBitmap() macro is usually obtained with the LoadBitmap() function previously discussed. 25.3.3 Obtaining Bitmap Dimensions Bitmap functions often require information about the dimensions and other charac - teristics of the bitmap. For example, the function most often used to display a bitmap is BitBlt(); it requires the width and height of the bitmap. If the bitmap is loaded as a resource from a file, the application must obtain the bitmap dimensions before blitting it to the screen. The GetObject() function is used to obtain informa- tion about a bitmap. The function's general form is as follows: int GetObject( HGDIOBJ hgdiobj, // l int cbBuffer, // 2 LPVOID lpvObject // 3 ); The first parameter is the handle to a graphics object; in this case, the handle to a bitmap. The second parameter is the size of the buffer that holds the informa - tion returned by the call. In the case of a bitmap, this parameter can be coded as sizeof (BITMAP). The third parameter is a pointer to the buffer that holds the in - formation returned by the call. In the case of a bitmap, the buffer is a structure variable of type BITMAP. The BITMAP structure is defined as follows: typedef struct tagBITMAP { LONG bmType; // Must be zero LONG bmWidth; // bitmap width (in pixels) LONG bmHeight; // bitmap height (in pixels) LONG bmWidthBytes; // bytes per scan line WORD bmPlanes; // number of color planes WORD bmBitsPixel; // bits per pixel color LPVOID bmBits; // points to bitmap values array } BITMAP; The structure member bmType specifies the bitmap type. It must be zero. The member bmWidth specifies the width, in pixels, of the bitmap. Its value must be greater than zero. The member bmHeight specifies the height, in pixels, of the bitmap. The height must be greater than zero. The bmWidthBytes member speci - fies the number of bytes in each scan line. Since Windows assumes that the bitmap is word-aligned, its value must be divisible by 2. The member bmPlanes 694 Chapter 25 specifies the number of color planes. The member bmBitsPixel specifies the number of bits required to indicate the color of a pixel. The member bmBits points to the lo - cation of the bit values for the bitmap. It is a long pointer to an array of charac - ter-size values. When the target of the GetObject() call is a bitmap, the information returned is the structure members related to the bitmap width, height, and color format. The GetObject() function cannot be used to read the value of the pointer to the bitmap data in the bmBits structure member. GetDIBits() retrieves the bit data of a bitmap. The mapping mode can also be a factor in regard to bitmap data. The GetObject() function returns the bitmap width and height in the BITMAP structure. The values returned are in pixels, which are device units. This works well if the mapping mode of the memory device context is MM_TEXT, but is not acceptable in any of the map - ping modes that use logical units. The DPtoLP() function allows the conversion of device coordinates (pixels) into logical coordinates for a particular device context. The function's general form is as follows: BOOL DPtoLP( HDC hdc, // 1 LPPOINT lpPoints, // 2 int nCount // 3 ); The first parameter identifies the device context. In the case of a bitmap, it is a memory device context. The second parameter points to an array of POINT struc- tures that holds the transformed values for the x- and y-coordinates. The third pa- rameter holds the number of points in the array specified in the second parameter. The function returns TRUE if it succeeds and FALSE if it fails. A bitmap size is defined by two values: the x-coordinate is the width and the y-coordinate the height. When a call to DPtoLP() is made to obtain the bitmap size, the third parameter is set to 1. This indicates that the coordinates to be transformed refer to a single point. By the same token, the second parameter is a pointer to a sin - gle POINT structure that holds the bitmap width in the x member and the bitmap height in the y member. 25.3.4 Blitting the Bitmap Once a bitmap has been selected onto a memory device context, and the code has ob - tained the necessary information about its width and height, it is possible to display it at any screen position by blitting the memory stored bitmap onto the screen. The BitBlt() function is the simplest and most direct method of performing the bitmap dis - play operation. The function's general form is as follows: BOOL BitBlt( HDC hdcDest, // 1 int nXDest, // 2 int nYDest, // 3 int nWidth, // 4 int nHeight, // 5 HDC hdcSrc, // 6 Displaying Bit-Mapped Images 695 int nXSrc, // 7 int nYSrc, // 8 DWORD dwRop // 9 ); The first parameter identifies the destination device context. If the call to BitBlt() is made to display a bitmap, this will be the display context. The second and third parameters are the x- and y-coordinates of the upper-left corner of the destination rectangle. Which is also the screen location where the upper-left cor - ner of the bitmap is displayed. The fourth and fifth parameters are the width and height of the bitmap, in logical units. The sixth parameter is the source device context. In the case of a bitmap display operation, this parameter holds the mem - ory device context where the bitmap is stored. The seventh and eighth parameters are the x- and y-coordinates of the source bitmap. Since the blitted rectangles must be of the same dimensions, as defined by the fourth and fifth parameters, the seventh and eighth parameters are usually set to zero. The ninth parameter defines the raster operation code. These codes are called ternary raster operations. They differ from the binary raster operation codes (ROP2) discussed in Chapter 22 in that the ternary codes take into account the source, the destination, and a pattern determined by the brush currently selected in the device context. There are 256 possible raster operations, fifteen of which have symbolic names defined in the windows.h header file. The raster operation code determines how the color data of the source and destination rectangles, to- gether with the current brush, are to be combined. Table 25.2 lists the fifteen ras- ter operations with symbolic names. Table 25.2 Symbolic Names for Raster Operations NAME DESCRIPTION BLACKNESS Fills the destination rectangle using the color associated with index 0 in the physical palette. The default value is black. DSTINVERT Inverts the destination rectangle. MERGECOPY Merges the colors of the source rectangle with the specified pattern using an AND operation. MERGEPAINT Merges the colors of the inverted source rectangle with the colors of the destination rectangle using an OR operation. NOTSRCCOPY Inverts the bits in the source rectangle and copies it to The destination. NOTSRCERASE Combines the colors of the source and destination rectangles using an OR operation, and then inverts the result. PATCOPY Copies the specified pattern to the destination bitmap. PATINVERT Combines the colors of the specified pattern with the colors of the destination rectangle using an XOR operation. (continues) 696 Chapter 25 Table 25.2 Symbolic Names for Raster Operations (continued) NAME DESCRIPTION PATPAINT Combines the colors of the pattern with the colors of the inverted source rectangle using an OR operation. The result of this operation is combined with the colors of the destination rectangle using an OR operation. SRCAND Combines the colors of the source and destination rectangles using an AND operation SRCCOPY. Copies the source rectangle directly to the destination rectangle. This is, by far, the most-used mode in bitblt operations. SRCERASE Combines the inverted colors of the destination rectangle with the colors of the source rectangle using an AND operation. SRCINVERT Combines the colors of the source and destination rectangles using an XOR operation. SRCPAINT Combines the colors of the source and destination rectangles using an OR operation. WHITENESS Fills the destination rectangle using the color associated with index 1 in the physical palette. The default value is White. 25.3.5 A Bitmap Display Function Displaying a bitmap is a multistage process that includes the following operations: 1. Creating a memory device context. 2. Selecting the bitmap into the memory device context. 3. Obtaining the bitmap dimensions and converting device units to logical units. 4. Blitting the bitmap onto the screen according to a ternary raster operation code. Many graphics applications can make use of a function that performs all of the previous operations. The function named ShowBitmap() is used in the Bitmap Demo project on the book's software on-line. The function's prototype is as follows: void ShowBitmap (HDC, HBITMAP, int, int, DWORD); | | | ||||| 12345 The first parameter is the handle to the device context. The ShowBitmap() func - tion creates its own memory device context. The second parameter is the handle to the bitmap that is to be displayed. The third and fourth parameters are the screen coordinates for displaying the upper-left corner of the bitmap. The fifth parameter is the ternary ROP code used in blitting the bitmap. If this parameter is NULL then the bitmap is displayed using the SRCCOPY raster operation. The following is a listing of the ShowBitmap() function: Displaying Bit-Mapped Images 697 void ShowBitmap (HDC hdc, HBITMAP hBitmap, int xStart, int yStart,\ DWORD rop3) { BITMAP bm; // BITMAP structure HDC memoryDc; // Handle to memory DC POINT ptSize; // POINT for DC POINT ptOrigin; // POINT for memory DC int mapMode; // Mapping mode // Test for NULL ROP3 code if (rop3 == NULL) rop3 = SRCCOPY; memoryDc = CreateCompatibleDC (hdc); // Memory device // handle mapMode = GetMapMode (hdc); // Obtain mapping // mode SetMapMode (memoryDc, mapMode); // Set memory DC // mapping mode // Select bitmap into memory DC // Note: assert statement facilitates detecting invalid // bitmaps during program development assert (SelectBitmap (memoryDc, hBitmap)); // Obtain bitmap dimensions GetObject (hBitmap, sizeof(BITMAP), (LPVOID) &bm); // Convert device units to logical units ptSize.x = bm.bmWidth; ptSize.y = bm.bmHeight; DPtoLP (hdc, &ptSize, 1); ptOrigin.x = 0; ptOrigin.y = 0; DPtoLP (memoryDc, &ptOrigin, 1); // Bitblt bitmap onto display memory BitBlt( hdc, xStart, yStart, ptSize.x, ptSize.y, memoryDc, ptOrigin.x, ptOrigin.y, rop3); // Delete memory DC with bitmap DeleteDC (memoryDc); } 25.4 Bitmap Manipulations In addition to displaying a bitmap stored in a disk file, graphics applications often need to perform otherbitmap-related operations. The following are among the most common operations: • Creating and displaying a hard-coded bitmap • Creating a bitmap in heap memory • Creating a blank bitmap and filling it by means of GDI functions • Creating a system-memory bitmap which applications can access directly 698 Chapter 25 • Using a bitmap to create a pattern brush 25.4.1 Hard-Coding a Monochrome Bitmap With the facilities available in Developer Studio for creating bitmaps, the programmer is seldom forced to hard-code a bitmap. Our rationale for discussing this option is that hard-coding bitmaps is a basic skill for a programmer, and that it helps to understand bitmaps in general. A monochrome bitmap has one color plane and is encoded in a one-bit-per-pixel format. In Windows, a monochrome bitmap is displayed by showing the 0-bits in the foreground color and the 1-bits in the background color. If the screen has a white foreground and a black background, 0-bits in the bitmap are displayed as white pix - els, and vice versa. If the bitmap is to be blitted on the screen using the BitBlt() func - tion, the action of the bits can be reversed by changing the raster operation code. This gives the programmer the flexibility of using either zero or one bits for back - ground or foreground attributes. Figure 25.4 shows a hard-coded monochrome bitmap. Figure 25.4 Hard-Coded, Monochrome Bitmap Displaying Bit-Mapped Images 699 0 0 1 2 3 4 5 6 7 8 9 431 bitmap: 2 01234 0- 0xC6 0x7C 0xC1 0x81 0xF0 1- 0xC6 0x7C 0xC1 0x83 0xF8 2- 0xC6 0x60 0xC1 0x83 0x18 3- 0xC6 0x60 0xC1 0x83 0x18 4- 0xFE 0x78 0xC1 0x83 0x18 5- 0xFE 0x78 0xC1 0x83 0x18 6- 0xC6 0x60 0xC1 0x83 0x18 7- 0xC6 0x60 0xC1 0x83 0x18 8- 0xC6 0x7C 0xF9 0xF3 0xF8 9- 0xC6 0x7C 0xF9 0xF1 0xF0 11000110=0xC6 effective size = 37 pixels In Figure 25.4 the dark pixels in the image are represented by 0-bits in the bitmap. The resulting data structure has five bytes per scan line and a total of 10 scan lines. The illustration shows how eight pixels in the bottom row of the image are represented by eight bits (one byte) of the bitmap. The dark pixels are en - coded as 0-bits and the light pixels as 1-bits. In order to display this bitmap so that the letters are black on a white screen background, the black and white pixels have to be reversed by changing the raster operation mode from the default value, SCRCOPY, to NOTSCRCOPY, as previously explained. Once the bit image of a monochrome bitmap has been calculated, we can pro - ceed to store this bit-to-pixel information in an array of type BYTE. Windows re - quires that bitmaps be word-aligned; therefore, each scan line in the array must have a number of bytes divisible by 2. In regards to the bitmap in Figure 25.4, you would have to add a padding byte to each scan line in order to satisfy this require - ment. The resulting array could be coded as follows: // 012345 static BYTE hexBits[] = {0xc6, 0x7c, 0xc1, 0x81, 0xf0, 0x0, 0xc6, 0x7c, 0xc1, 0x83, 0xf8, 0x0, 0xc6, 0x60, 0xc1, 0x83, 0x18, 0x0, 0xc6, 0x60, 0xc1, 0x83, 0x18, 0x0, 0xfe, 0x78, 0xc1, 0x83, 0x18, 0x0, 0xfe, 0x78, 0xc1, 0x83, 0x18, 0x0, 0xc6, 0x60, 0xc1, 0x83, 0x18, 0x0, 0xc6, 0x60, 0xc1, 0x83, 0x18, 0x0, 0xc6, 0x7c, 0xf9, 0xf3, 0xf8, 0x0, 0xc6, 0x7c, 0xf9, 0xf1, 0xf0, 0x0}; // | // padding byte | The CreateBitmap() function can be used to create a bitmap given the bit-to-pixel data array. The function's general form is as follows: HBITMAP CreateBitmap( int nWidth, // 1 int nHeight, // 2 UINT cPlanes, // 3 UINT cBitsPerPel, // 4 CONST VOID *lpvBits // 5 ); The first parameter is the actual width of the bitmap, in pixels. In relation to the bitmap in Figure 25.4, this value is 37 pixels, as shown in the illustration. The second parameter is the number of scan lines in the bitmap. The third parameter is the number of color planes. In the case of a monochrome bitmap this value is 1. The fourth parameter is the number of bits per pixel. In a monochrome bitmap this value is also 1. The fifth parameter is a pointer to the location where the bitmap data is stored. If the function succeeds, the returned value is the handle to a bitmap. If the function fails, the return value is NULL. The following code frag - ment initializes a monochrome bitmap using the bitmap data in the hexBits[] ar - ray previously listed: static HBITMAP bmImage1; . 700 Chapter 25 . . // Initialize monochrome bitmap bmImage1 = CreateBitmap (37, 10, 1, 1, hexBits); Alternatively, a bitmap can be defined using a structure of type BITMAP, listed previously in this chapter and in Appendix F. Before the bitmap is created, the struc - ture members must be initialized, as in the following code fragment: static BITMAP monoBM; . . . // Initialize data structure for a monochrome bitmap monoBM.bmType = 0; // must be zero monoBM.bmWidth = 37; // actual pixels used monoBM.bmHeight = 10; // scan lines monoBM.bmWidthBytes = 6; // width (must be word aligned) monoBM.bmPlanes = 1; // 1 for monochrome bitmaps monoBM.bmBitsPixel = 1; // 1 for monochrome bitmaps monoBM.bmBits = (LPVOID) &hexBits; // address of bit field When the bitmap data is stored in a structure of type BITMAP, the bitmap can be created by means of the CreateBitmapIndirect() function. The function's general form is as follows: HBITMAP CreateBitmapIndirect( CONST BITMAP *lpbm // 1 ); The function's only parameter is a pointer to a structure of type BITMAP. If the function succeeds, the returned value is the handle to a bitmap. If the function fails, the return value is NULL. The following code fragment uses CreateBitmapIndirect() to initialize a monochrome bitmap using the bitmap data in the hexBits[] array pre - viously listed: static HBITMAP bmImage1; . . . // Initialize monochrome bitmap bmImage1 = CreateBitmapIndirect (&monoBM); Whether the bitmap was created using CreateBitmap() or CreateBitmapIndirect(), it can now be displayed by means of the ShowBitmap() function developed and listed previously in this chapter. 25.4.2 Bitmaps in Heap Memory A bitmap can take up a considerable amount of memory or storage resources. For ex - ample, a 1200-by-1200 pixel bitmap encoded in 32-bit color takes up approximately 5.7 Mb. Applications that store large bitmaps in their own memory space can run into memory management problems. One possible solution is to store large bitmaps in dy - namically allocated memory, which can be freed as soon as the bitmap is no longer needed. Note that freeing memory where the bitmap is stored does not affect the screen image. Displaying Bit-Mapped Images 701 Several programming techniques can be used to allocate and release heap memory for a bitmap. The one most suitable depends on the particular needs of each particular programming problem. In one case you may allocate heap memory for a bitmap during WM_CREATE message processing, and then use this allocated space to create or copy different bitmaps during program execution. The allo - cated memory can then be freed during WM_DESTROY processing. Another op - tion is to allocate memory at the time it is required, create or copy the bitmap to this allocated space, and deallocate the memory when the bitmap is no longer needed. Many fables and fantastic theories have originated in the complications and misunderstandings of Windows memory management. Although most of these problems were corrected in Windows 3.1, an entire programming subculture still thrives on discussions related to these topics. A programmer encountering mem - ory management in Windows finds that there are three separate sets of memory al - location and deallocation operators that serve apparently identical purposes: the C++ operators new and delete, the traditional C operators malloc and free, and the Windows kernel functions LocalAlloc(), GlobalAlloc(), LocalFree(), and GlobalFree(). In Win32 programming, the first simplification is a result of the fact that there is no difference between the global and the local heaps. Therefore, GlobalAlloc() and LocalAlloc(), as well as GlobalFree() and LocalFree(), actually perform virtu- ally identical functions. Because of their greater flexibility we will use GlobalAlloc() and GlobalFree() instead of new and delete or malloc and free oper- ators from the C++ and C libraries. Another reason for this preference is that most Windows compilers implement malloc and new in terms of GlobalAlloc(); therefore, the traditional operators offer no advantage. Traditionally, three types of memory are documented as being available to ap - plications: fixed memory, moveable memory, and discardable memory. The justifi - cation for preferring moveable memory disappeared with Windows 95, in which a memory block can be moved in virtual memory while retaining the same address. For the same reason, the use of fixed memory no longer needs to be avoided. Discardable memory is only indicated when the data can be easily recreated, which is not usually the case with image data structures. In conclusion, fixed memory is usually quite suitable for dynamically storing bitmaps and other image data. Note that the terms moveable and movable are both accepted, although mov - able is preferred. However, the Windows API contains the constants GMEM_MOVEABLE and LMEM_MOVEABLE. For this reason we have used the former. In this section we discuss the bare essentials of memory allocation and deallocation in Windows. The topic of Windows memory management can easily fill a good-size volume. Graphics applications are often memory-intensive and may require sophisticated memory management techniques. A graphics program - 702 Chapter 25 mer should have a thorough knowledge of Win32 memory architecture, virtual mem - ory, and heap management. The book Advanced Windows, by Richter (see Bibliography) has chapters devoted to each of these topics. The GlobalAlloc() function is used to allocate memory from the default heap. The default heap is initially 1Mb, but under Windows, this heap grows as it becomes nec - essary. The function's general form is as follows: HGLOBAL GlobalAlloc( UINT uFlags, // 1 DWORD dwBytes // 2 ); The first parameter is a flag that determines how memory is allocated to the caller. Table 25.3 lists the most commonly used allocation flags. The second parame - ter is the number of bytes of memory to be allocated. If it succeeds, the function re - turns the handle to the allocated memory object. If the allocation flag is GMEM_FIXED, the handle can be directly cast into a pointer and the memory used. If the allocated memory is not fixed, then it must be locked using GlobalLock() be - fore it can be used by code. The function returns NULL if the allocation request fails. Table 25.3 Win-32 Commonly Used Memory Allocation Flags FLAG MEANING GMEM_FIXED Allocates fixed memory. This flag cannot be combined with the GMEM_MOVEABLE or GMEM_DISCARDABLE flag. The return value is a pointer to the memory block. GMEM_MOVEABLE Allocates moveable memory. This flag cannot be combined with the GMEM_FIXED flag. The return value is the handle of the memory object, which is a 32-bit quantity private to the calling process. GMEM_DISCARDABLE Allocates discardable memory. This flag cannot be combined with the flag. Win32-based operating systems ignore this flag. GMEM_ZEROINIT Initializes memory to 0. GPTR Combines the GMEM_FIXED and GMEM_ZEROINIT flags. GHND Combines the GMEM_MOVEABLE and GMEM_ZEROINIT flags. The process of creating a bitmap in heap memory and displaying it on the video screen can be accomplished by the following steps: 1. Dynamically allocate the memory required for the bitmap and the corresponding data structures. 2. Store the bitmap data and the bitmap dimensions and color information, thus creating a DIB. 3. Convert the device independent bitmap (DIB) into a device dependent bitmap using CreateDIBitmap(). 4. Display the bitmap using SetDIBitsToDevice(). Displaying Bit-Mapped Images 703 [...]... standardization For instance, different types of belts and pulleys are available off-the-shelf for adapting the motor to various devices Also, the electric power is standardized so that the motor generates the same power and revolutions per minute in the various applications Perhaps the most important reason for promoting software reusability is that it reduces the cost of production On the other hand,... proportionally insignificant 26.1.1 Software Qualities An engineered product is usually associated with a list of qualities that define its usability For example, in performing its functions a bridge supports a predetermined weight and withstands a given wind force An airplane is capable of transporting a specific load, at a certain speed and altitude By the same token, a software product is associated... device context and the sixth parameter is the source device context The second and third parameters are the x- and y-coordinates of the upper-left corner of the destination rectangle The fourth and fifth parameters are the width and height of the destination rectangle The seventh and eighth parameters are the x- and y-coordinates of the upper-left corner of the source rectangle The ninth and tenth parameters... engineering was first introduced in the 196 0s in an effort to treat more rigorously the often frustrating task of designing and developing computer programs It was around this time that the computer community became increasingly worried about the fact that software projects were typically over budget and behind schedule The term software crisis came to signify that software development was the bottleneck... theories, and techniques for building bridges and airplanes, we should also be capable of straightforwardly developing a scientific methodology for engineering software 723 724 Chapter 26 The programmer productivity fallacy relates to the fact that computer programming, unlike ditch digging or apple harvesting, is not a task that is easily partitioned into isolated functions that can be performed independently... used, then the brush and the destination bitmap are combined by performing a boolean XOR operation The remaining raster operation codes that are documented for the PatBlt() function with symbolic names (DSTINVERT, BLACKNESS, and WHITENESS) ignore the brush and are useless in a pattern block transfer The raster operation performed by PatBlt() is a binary one since it combines a pattern and a destination... CreateDIBSection() function, first introduced in Win32 and formalized in Windows 95 , allows creating a device-independent bitmap that applications can access directly Note that the original Windows documentation for Win32 contained incorrect information about the CreateDIBSection() function and the associated DIBSECTION structure Some of the errors and omissions were later corrected so that current documentation... is that it reduces the cost of production On the other hand, reusability of software components is often difficult to achieve because of lack of standardization For example, the search engine developed for a word processor may not be directly usable in another one due to variations in the data structures used for storing and formatting the text file Or a mathematical routine that calculates the square... specific hardware or software properties, to achieve a particular functionality for their products This decision often implies a substantial sacrifice in portability Other Properties Many other properties of software are often mentioned in software engineering textbooks, among them are timeliness, visibility, productivity, interoperability, and understandability In special circumstances these and other properties... otherwise performs as expected Computer programs, on the other hand, often fail catastrophically When this happens it is difficult for the user to appreciate any residual usefulness in the software product This leads to the conclusion that rather than a cumulative quality effect, software production is subject to a minimal quality rule, which determines that a relatively small defect in a software product . Studio for creating bitmaps, the programmer is seldom forced to hard-code a bitmap. Our rationale for discussing this option is that hard-coding bitmaps is a basic skill for a programmer, and that. bits for back - ground or foreground attributes. Figure 25.4 shows a hard-coded monochrome bitmap. Figure 25.4 Hard-Coded, Monochrome Bitmap Displaying Bit-Mapped Images 699 0 0 1 2 3 4 5 6 7 8 9 431 bitmap: 2 01234 0-. GlobalFree() and LocalFree(), actually perform virtu- ally identical functions. Because of their greater flexibility we will use GlobalAlloc() and GlobalFree() instead of new and delete or malloc and

Ngày đăng: 12/08/2014, 07:22

Tài liệu cùng người dùng

Tài liệu liên quan