If the hard body is allowed, this chapter does not exist. Although many modern display cards offer 24-bit color (also known as "True Color" or "T300,000") or 16-bit color ("enhanced color" or "tens of thousands of colors"), some display cards - especially It is in a portable computer or in high-resolution mode - only 8 bits per key. This means that only 256 colors.
What can we do with 256 colors? Obviously, to display the image of the real world, only 16 colors are not enough, at least thousands or millions of colors, 256 colors are located in the middle state. Yes, with 256 colors to display the real-world image is sufficient, but they need to specify these colors based on a particular image. This means that the writer system does not simply select 256 colors of the "Standard" series, and hopes that they are ideal for each application.
This is the full content involved in the Windows Toner Manager. It is used to specify the color required when executed in 8-bit metallic display mode. If you know the program is definitely not executed in 8-bit chamfered mode, you don't need to use a palette manager. However, since some details of the dot matrix are added, this chapter is still important information.
Take a palette
Traditionally, the palette is a plate for painters to mix colors. This word can also refer to all the colors used in the painting process. In computer graphics, the toner is a range of color available on a graphic output device (eg, a video display). This noun can also refer to a comparison table that supports a 256-color mode display card.
Video hardware
The operation process of the palette on the display card is shown in the following figure:
In the 8-bit dollar display mode, each of the totes accounts for 8 bits. The status query contains the location of the control table of 256RGB values. These RGB values can be exactly 24-bit yuan, or small, usually 18-bit yuan width (ie, the main red, green and blue each of the blue). The value of each color is input to a digit class than the converter to obtain three-class ratio signals sent to the monitor.
Typically, the software can be used to load the color panel comparison table with any value, but this is a window interface that is independent of the device, such as Microsoft Windows, there will be some interference. First, Windows must provide a soft interface to access the Toner Disk Manager without direct interference hardware. The second problem is more serious: Because all applications share the same video display, and simultaneously executed, an application uses a palette comparison table that may affect other programs.
At this time, you need to use the Windows Toner Manager (proposed in Windows 3.0). Windows retains 20 of 256 colors, while allowing applications to modify the rest of the 236. (In some cases, the application can change 254 species in 256 colors - except for black and white - but this is a bit of trouble). Windows is shown in 20 colors (sometimes referred to as 20 "static" colors for the system.
Table 16-1 20 Reserved Colors in Color Display Mode
图 位 元 RGB value color name 图 位 元 RGB value color name 00000000 00 00 00] 000000000000 00 00 00 00000000000000000018 000 00 00 00 00 00 00 00000011 80 80 00 00 00 00 ff blue 00000100 00 00 0 暗 蓝 11111011 FF 00 黄 000001010 00 80 8 洋 红 111110 00 FF 00 Green 00000110 00 80 暗 青 11111001 FF 00 00 ★ 00 00000111 C0 C0 C0 bright gray 1111000 80 80 80 Dark Green 111000 C0 DC C0 Green 11110111 A0 A4 Neutrality 00001001 A6 CA F0 Sky Blue 11110110 FF FE F0 Milk White In 256 Color Display Mode Perform, this coloring disk is maintained by the Windows maintenance system. The hardware palette on the display card is the same. The internal system palette is shown in Table 16-1. The application can modify the remaining 236 colors by specifying the "logical palettes". If there are multiple applications to use the logical tile, Windows gives the highest priority window (we know, the active window has highlighting the title column, and is displayed in front of all other windows). We will use some simple paradigm to check how it works.
To perform the program in this chapter, you may need to switch the display card to 256 color mode. Right click on the desktop, select "Properties" from the menu, then select the "Settings" page label.
Show grayscale
The Grays1 program indicated by the program 16-1 does not use the Windows Toner Manager, and attempts to use the 65-level race of normal display as a variety of colors from black to white.
Cheng 16-1 grays1.c / * ----------------------------------------- ---------------------------------- Grays1.c - gray shades (c) Charles Petzold, 1998 - -------------------------------------------------- ------------------------- * /
#include
wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor (NULL , IDC_ARROW); wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szAppName;! if (RegisterClass (& wndclass)) {MessageBox (NULL, TEXT ( "This program requires Windows NT! "), szAppName, MB_ICONERROR); return 0;} hwnd = CreateWindow (szAppName, TEXT (" Shades of Gray # 1 "), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ShowWindow ( HWnd, ICMDSHOW; UPDATEWINDOW (HWND); While (GetMessage (& MSG, NULL, 0, 0)) {TranslateMessage (& MSG); DispatchMessage (& MSG);} Return Msg.wParam;}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {static int cxClient, cyClient; HBRUSH hBrush; HDC hdc; int i; PAINTSTRUCT ps; RECT rect; switch (message) {case WM_SIZE: cxClient = LOWORD ( LPARAM; cyclient = HiWord (LPARAM); Return 0; Case WM_Paint: HDC = BeginPaint (HWND, & PS);
// Draw the Fountain of Grays
For (i = 0; i <65; i ) {rect.Left = i * cxclient / 65; Rect.top = 0; Rect.right = (i 1) * cxclient / 65; Rect.bottom = cyclient;
Hbrush = Createsolidbrush (RGB (MIN (255, 4 * I), MIN (255, 4 * I))); FillRect (HDC, & Rect, Hbrush); deleteObject (Hbrush); Endpaint (hwnd, & ps); Return 0;
Case WM_DESTROY: PostquitMessage (0); Return 0;} Return DEFWINDOWPROC (HWND, Message, WPARAM, LPARAM);} During the WM_PAINT message processing, the program calls 65 FillRect functions, each uses different grayscale creation brush. The gray length value is RGB value (0, 0, 0), (4, 4, 4), (8, 8, 8), etc. until the last value (255, 255, 255). The last value comes from the MIN huge set in the CreateSolidbrush. If the program is executed in 256 color display mode, you will see 65 grayscale from black to white, and they almost colored. The pure color is only black, dark gray (128, 128, 128), bright gray (192, 192, 1992) and white. Other colors are mixed multi-bit modes of these pure colors. If we are displaying rows or text, instead of using this 65 grayscale fill area, Windows will not use mix colors and use only these four solid colors. If we are displaying a dot mapping, the image will be approximated with 20 standard Windows colors. At this time, it is like the program you are in the final chapter, which is also available in color or grayscale DIB. Typically, Windows is not used in dot matrix.
The grays2 shown in the formula 16-2 verifies the most important functions and messages in the Tonet Manager with less external program.
Co-style 16-2 grays2grays2.c / * ----------------------------------------- --------------------------------- Grays2.c - gray shades sale pasampte manager (c) Charles Petzold, 1998 ------------------------------------- ---------------------------- * /
#include
wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor (NULL , IDC_ARROW); WNDCLASS.HBRBACKGROUND = (Hbrush) getStockObject (white_brush); WNDCLASS.LPSZMENUNUNAME = NULL; WNDCLASS.LPSZCLASSNAME = szappname;
if {MessageBox (NULL, TEXT ( "This program requires Windows NT!"), szAppName, MB_ICONERROR); return 0;} (RegisterClass (& wndclass)!) hwnd = CreateWindow (szAppName, TEXT ( "Shades of Gray # 2") , WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ShowWindow (hwnd, iCmdShow); UpdateWindow (hwnd); while (GetMessage (& msg, NULL, 0, 0)) {TranslateMessage (& msg) ; DispatchMessage (& msg);} return msg.wParam;} LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {static HPALETTE hPalette; static int cxClient, cyClient; HBRUSH hBrush; HDC hdc; int i; LOGPALETTE * PLP; PAINTSTRUCT PS; Rect Rect; Switch (Message) {Case WM_CREATE: // SET UPA LOGPALETTE STRUCTURE AND CREATE A PALETTE
PLP = Malloc (SizeOf (Logpalette) 64 * Sizeof (Paletteentry));
PLP-> Palversion = 0x0300; PLP-> PALNUMENTRIES = 65;
For (i = 0; i <65; i ) {plp-> palpalent [i] .pled = (byte) min (255, 4 * i); plp-> palpalent [i] .pegreen = (byte) min 255, 4 * i); plp-> palpalentry [i] .peblue = (byte) min (255, 4 * i); plp-> palpalent [i] .peflags = 0;} HPALETTE = CREATEPALETTE (PLP); Free (PLP); RETURN 0;
Case WM_SIZE: CXClient = Loword (LPARAM); cyclient = HiWord (LPARAM); Return 0; Case WM_Paint: HDC = BeginPaint (HWND, & PS);
// select and realize the Palette in The Device Context
SelectPalette (HDC, HPALETTE, FALSE); REALIZEPALETTE (HDC);
// Draw the Fountain of Grays
For (i = 0; i <65; i ) {Rect.Left = i * cxclient / 64; Rect.top = 0; Rect.right = (i 1) * cxclient / 64; rect.bottom = cyclient;
Hbrush = Createsolidbrush (Palettergb (min (255, 4 * i), min (255, 4 * i))); FillRect (HDC, & Rect, Hbrush); deleteObject (Hbrush);} Endpaint (hwnd, & ps); Return 0; Case WM_QuerynewPalette: if (! Hpalette) Return False;
HDC = Getdc (HWND); SelectPalette (HDC, HPALETTE, FALSE); RealizePalette (HDC); InvalidateERECT (HWND, NULL, TRUE);
ReleaseDC (HWND, HDC); Return True;
Case WM_PALETTECHANGED: IF (! hpalette || (hwnd) wparam == hwnd) Break;
HDC = GETDC (HWND); SelectPalette (HDC, HPALETTE, FALSE); REALIZEPALETTE (HDC); UpdateColors (HDC); ReleaseDC (HWND, HDC); BREAK
Case WM_DESTROY: DeleteObject (HPALETTTE); PostquitMessage (0); return 0;} Return DEFWINDOWPROC (HWND, Message, WPARAM, LPARAM); Palette. The logical color tray contains all the colors needed in the program - ie 236 colors. Grays1 processes this job during WM_CREATE message processing. It initializes the field of the LogPalette ("Logical Palette: Logic Tour") structure, and passes the indicator of this structure to the CreatePalette function. CreatePalette Removes the code of the logical color tray and stores this code in a static variable hPalette.
The Logpalette structure is defined as follows:
Typedef strunt {Word Palversion; Word PalNumentries; Paletteentry Palpalent [1];} Logpalette, * PLOGPALETTE; The first field is usually set to 0x0300, indicating compatible Windows 3.0. The second field is set to the number of items in the color disc table. The third field in the Logpalette structure is an array of a PaletteEntry structure, which is also a palette item. The PaletteEntry structure is defined as follows:
TYPEDEF STRUCT {byte Pegreen; Byte Peblue; Byte Peflags;} Paletteentry, * PPALETTEENTRY; Each PaletteEntry structure defines a RGB color value we want to use in the palette.
Note that the array of a PaletteEntry structure can only be defined in LogPalette. You need to configure enough memory space for the LogPalette structure and the additional PaletteEntry structure. Grays2 requires 65 grayscale, so it is equipped with a large enough memory space for the Logpalette structure and 64 additional PaletteEntry structures. Grays2 set the PALNUMENTRIES field to 65, then from 0 to 64 rounds, calculate the gray class level (generally four times the loop index, but not more than 255), set the PERED, Pegreen and Peblue fields in the structure It is set to this grayscale level. The PEFLAGS field is set to 0. The program will be directed to the index of this memory block to createPalette, store the toner disc server in a static variable, then release the memory. The logical color panel is a GDI object. The program should delete all of their logical tunnels established. WndProc calls DeleteObject through WM_DESTROY message processing, and carefully delete the logical tangle.
Note that the logical color panel is a separate device content. Before you really use, you must ensure that it is selected to enter the device content. During WM_PAINT message processing, SelectPalette selects the logical palette to enter the device content. In addition to the third parameters, this fifth is similar to the SelectObject function. Typically, the third parameter is set to False. If the third parameter of SELECTPALETT is set to True, the color panel will always be "Background Tunge", which means that when all of the other programs have shown their respective palette, the color panel can still be obtained. An unused item in the system palette.
Only one logical color tank can select the device content at any time. The function will pass back the logical color palette of the previous selection device content. If you want to re-select the content of the device, you can store this code.
By mapping the color to the system palette, the REALIZEPALETTE correspondence makes Windows "display" logical papermarking in the device content, and the system palette corresponds to the actual color palette of the display card. Actual work is done during this functions. Windows must determine whether the window of the call fifth is active or non-active, and notify the system color panel change to other windows as much as possible (we will briefly explain the procedure for notification).
Recalling Grays1, which uses RGB gauge to specify the color of the solid color painting brush. RGB Male is constructed a 32-bit long integer (recorded as a ColorRef value), where the high tuning is 0, 3 low tuning is red, green and blue brightness.
The program using the Windows Toner Manager can continue to use the RGB color value to specify the color. However, these RGB color values will not access additional colors in the logical palette. Their roles are the same as those that are not using the palette manager. To use additional colors in the logical color tray, you should use the Palettergb gauge. In addition to the high order of the colorref value 2 instead of 0, the color of the color palette RGB color is similar to the RGB color.
Here is an important rule:
In order to use the color in the logical palette, use a color panel RGB value or a torched copy to specify (I will briefly discuss the palette index). Do not use a regular RGB value. If a regular RGB value is used, you will get a standard color instead of the color in a logical palette. Do not use the toner RGB value or a torless disk index when the toner is selected. Although you can use a toner RGB value to specify the color of the logical color tray, you still have to get colors from the logical palette. For example, during GrayS2 Processing WM_PAINT, after you select and display the logical color panel, if you try to display the red, the grayshade will be displayed. You must use the RGB color value to select the color in the logical palette.
Note that Grays2 never checks the video to display the driver to support the palette management program. When GrayS2 is executed without supporting the display mode (ie, all non-256-color display modes), GRAYS2 is the same as GRASY1. Pammetric information
If the program specifies a color in the logical color tray, the color is one of the 20 reserved colors, then Windows will map the logical color palette item to the color. Also, if two or more applications specify the same color in their logical color trays, these applications will share the system palette items. The program can ignore this memory by specifying the PEFLAGS field of the PaletteEntry structure as constant PC_NOCOLLLLLLAPSE (the remaining two possible tags are pc_explicit (used to display system palette) and PC_RESERVED (for toner animation), I will These two markers are shown later in this chapter).
To help organize system palette, Windows Toner Manager contains two messages sent to the primary window.
The first is QM_QueryNewPalette. When the primary window activity, the message is sent to the main window. If the program uses a toner manager while painting on your window, it must handle the message. Grays2 demonstrates specific practices. The program obtains the device content code and selects a colorish disk, calls REALIZEPALETTE, and then invalidate the window to generate WM_PAint messages. If a logical color tray is displayed, the window message processing is transmitted back from the message, otherwise false.
When the system color displacement is changed to the result of the WM_QueryNewpalette message, Windows sends the WM_PALETTECHANGED message to all the main windows of the currently active window to start and terminate all the main features of the handling the window chain. This allows the front desk window to have priority. The WPARAM value passed to the window message processing program is the code of the activity window. This message is handled only when WPARAM is not equal to the program's window code.
Typically, when processed WM_PALETTECHANGED, any program with a self-contained color panel calls SelectPalette and RealizePalette. Subsequent Windows When you call RealizePalette during message processing, Windows first checks if the RGB color in the logical palette is matched to RGB colors loaded in the system palette. If the two prices need the same color, then these two programs use a system palette item. Next, Windows checks unused system palette items. If all have been used, the colors in the logical palette are mapped from 20 reserved items to the nearest colors.
If you don't care about the appearance of the area, you don't have to process the WM_Palettechanged message. Otherwise, you have two options. Grays2 displays one of them: When processing the WM_QueryNewPALETTE message, it obtains the contents of the device, selects a colorish disk, and then calls RealizePalette. At this time, you can call InvalIDateRect when processing WM_QueryNewPalette. Conversely, Grays2 calls UpdateColors. This function is usually more efficient than the new drawing window, and it changes the value of the chambers in the window to help protect the previous colors.
Many programs using the Thai Dish Manager will cause WM_QueryNewPALETTE and WM_PALETTECHANGED messages to be processed with the method displayed by Grays2.
Template index method
The Grays3 program shown in the formula 16-3 is very similar to Grays2, just uses the gauge of calling PaletteIndex during WM_PAINT, not Palettergb.
Program 16-3 grays3grays3.c / * ----------------------------------------- ---------------------------------- Grays3.c - gray shades use plette manager (c) Charles Petzold, 1998 ------------------------------------- ---------------------------- * / # include
if {MessageBox (NULL, TEXT ( "This program requires Windows NT!"), szAppName, MB_ICONERROR); return 0;} (RegisterClass (& wndclass)!) hwnd = CreateWindow (szAppName, TEXT ( "Shades of Gray # 3") , WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ShowWindow (hwnd, iCmdShow); UpdateWindow (hwnd); while (GetMessage (& msg, NULL, 0, 0)) {TranslateMessage (& msg) DispatchMessage (& MSG);} return msg.wpaham;}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {static HPALETTE hPalette; static int cxClient, cyClient; HBRUSH hBrush; HDC hdc; int i; LOGPALETTE * plp; PAINTSTRUCT ps; RECT rect; switch (message) {CASE WM_CREATE: / / SET UP A Logpalette Structure and Create a Palette
PLP = Malloc (SizeOf (Logpalette) 64 * sizeof (Paletteentry)); PLP-> Palversion = 0x0300; PLP-> PalNumentries = 65;
For (i = 0; i <65; i ) {plp-> palpalent [i] .pled = (byte) min (255, 4 * i); plp-> palpalent [i] .pegreen = (byte) min 255, 4 * i); plp-> palpalentry [i] .peblue = (byte) min (255, 4 * i); plp-> palpalent [i] .peflags = 0;} HPALETTE = CREATEPALETTE (PLP); Free (PLP); RETURN 0;
Case WM_SIZE: CXClient = Loword (LPARAM); cyclient = HiWord (LPARAM); Return 0; Case WM_Paint: HDC = BeginPaint (HWND, & PS);
// select and realize the Palette in The Device Context
SelectPalette (HDC, HPALETTE, FALSE); REALIZEPALETTE (HDC);
// Draw the Fountain of Grays
For (i = 0; i <65; i ) {Rect.Left = i * cxclient / 64; Rect.top = 0; Rect.right = (i 1) * cxclient / 64; rect.bottom = cyclient;
Hbrush = CreateSolidbrush (PaletteIndex (i));
FillRect (HDC, & Rect, Hbrush); deleteObject (Hbrush);
Endpaint (hwnd, & ps); Return 0;
Case WM_QUERYNEWPALETTE: IF (! hpalette) Return False;
HDC = getDC (HWND); SelectPalette (HDC, HPALETTE, FALSE); RealizePalette (HDC); InvalIdateRect (HWND, NULL, FALSE); ReleaseDC (HWND, HDC); Return True;
Case WM_PALETTECHANGED: IF (! hpalette || (hwnd) wparam == hwnd) Break;
HDC = getDC (hwnd); SelectPalette (HDC, HPALETTE, FALSE); RealizePalette (HDC); UpdateColors (HDC);
ReleaseDC (HWND, HDC); Break;
Case WM_DESTROY: PostquitMessage (0); Return 0;} Return DefWindowProc (HWND, Message, WPARAM, LPARAM);} The color of the "Toner" index is different from the color palette RGB color, its high tuning is 1, and low The value of the tuple is currently selected in the device content, the index in the logical palette. In GrayS3, there are 65 items in the logical color tray, and the index of these items is from 0 to 64. value
PaletteIndex (0) refers to black, PaletteIndex (32) refers to gray, and
PaletteIndex (64) finger white.
Because Windows does not need to perform search for the most color, use the toner index more efficient than using the RGB value.
Query color palette support
You can easily verify: When Windows is executed in 16-bit or 24-bit display mode, Grays2 and Grays3 are well implemented. However, in some cases, the Windows application to use the Paper Manager may define whether the device driver supports it. At this time, you can call getDeviceCaps and use the device content code and PASTERCAPS displayed as a parameter. The function will pass an integer consisting of a series of flags. Test the supported palette by executing a bit element operation between the return value and constant RC_PALETTE:
RC_PALETTE & GETDEVICECAPS (HDC, RasterCaps) If this value is non-zero, the video display device driver will support the palette operation. Under this circumstance, three other important items from getDeviceCaps are also available. Funny call
GetDeviceCaps (HDC, SizePalette) will pass the total size of the tag table on the display card. This is the same as the total number of colors shown. Because the palette manager is only used for the video display mode of the 8-bit element per image, this value will be 256.
Funny call
GetDeviceCaps (HDC, NumReServed) is transmitted in the color number in the tunnel disc, which is that the device driver is preserved, and this value is 20. Without calling the palette manager, these is just the solid color used in the Windows application in 256 color display mode. To use the remaining 236 colors, the program must use the palette manager.
An additional project is also available:
GetDeviceCaps (HDC, Colorres) This value tells you that the RGB color value resolution (in bitmometer) loaded to the hard body tag table. These are bit elements that enter the digits than the converter. Some video display cards use only 6-bit ADC, so this value is 18. The remaining 8-bit ADC is used, so the value is 24.
Windows adopts a color resolution and thus takes some movements. For example, if the color resolution is 18, the program will not be possible to request 128 grayscale, because only 64 discrete grayscale can be used. Requirement of 128 grayscale does not have to populate the hard color palette with excess projects.
System palette
I have mentioned earlier, the Windows system palette is directly consistent with the hard body color palette table on the display card (however, the hard body toner lookup table may be lower than the color resolution of the system color panel). The program can obtain certain or all RGB items in the system palette by calling the following.
GetSystemPaletteentries (HDC, USTART, UNUM, & PE); This function can be executed only when the display card mode supports the palette operation. The second and third parameters are no fixed-to-line integers, display the number of indexes and palette items of the first toner project. The last parameter is an indicator to the PaletteEntry type.
You can use the form in several cases. The program can define the PaletteEntry structure as follows:
PaletteEntry PE; then call getSystemPaletteentries multiple times by following the method:
GetSystemPaletteentries (HDC, I, 1, & PE); I is from 0 to a certain value, which is less than the value transmitted from getDeviceCaps (with SizePalette index 255). Alternatively, the program is to get all the system palette items, which can define the indicators to the PaletTeentry structure, and then reconfigure enough memory blocks to store the same multi-PaletteEntry structure with the color panel size. The GetSystemPaletteEntries function allows you to check the hardware tag table. The items in the system palette are arranged in sequence in the order of grain values, which are used to indicate the color in the video display buffer. I will simply discuss the specific practices.
Other palette functions
We have seen in front, the Windows program can change the system palette, but only indirect changes: the first step is established, which is basically the RGB color value array to be used in the program. The CreatePalette correspondence does not cause a system tissue or any change in the display card tag. The logical color tray must select the contents of the device and appear before anything occurs.
Program can be called
GetPaletteentries (HPALETTE, USTART, UNUM, & PE); to query the RGB color value in the logical palette. You can use this version as follows from the method using GetSystemPaleTeentries. However, it should be noted that the first parameter is the code of the logical color panel, rather than the code of the device content.
After establishing a logical palette, let you change the corresponding functions of the values:
SetPaletteentries (HPALETTEEENTERTRIES (HPALETTE, USTART, UNUM, & PE); In addition, remember that call this function does not cause any changes to the system's color tray - even if the current color tray is selected into the device content. This file also does not change the size of the logical color tray. To change the size of the logical color tray, use ResizePalette.
The following correspondence accepts the RGB color reference value as the final parameter and passes the index back to the logical paper, which corresponds to the RGB color value that is closest to it:
IINDEX = GetNearestPaletteIndex (HPALETTE, CR); the second parameter is a colorref value. If you want, call getPaletteEntries to get the actual RGB color value in the logical color tray.
If the program requires more than 236 custom colors in 8-bit chamfered mode, you can call GetSystemPaletteuse. This allows programs to set 254 custom colors; the system is only black and white. However, the program is only allowed when maximizing full screen, and it also sets some system colors to black and white, so that the title column and functional table are still visible.
Bit yuan mapping operation problem
From Chapter 5, you can understand that GDI allows the use of different "Painting Mode" or "bitmap operation" to draw lines and fill the area. The drawing mode is set with SETROP2, and "2" indicates a binary bitmap operation between two objects. The three-way block mapping operation is used to process Bitblt and similar functions. These bit mapping operations determine the combination of objects that are painting and surface icons. For example, you can draw a straight line so that the icon on the line is combined with the displayed graphic according to the component.
The bit element mapping operation is to operate in the order of the respective bits on the primary element. Changing the color tray will affect these bitmaps. The operating object of the bitmap operation is a primitive element, and these icons may not be associated with the actual color.
You can draw this conclusion through the GrayS2 or Grays3 program. When adjusting the size, drag the boundary of the top or bottom through the window, Windows uses the bitmap operation of the reverse background in the background of the primary element map to display the boundary of the drag size, and the purpose is to make the drag size boundary is always visible. However, in the Grays2 and Grays3 program, you will see the color of a variety of random transformations, these colors just with items that have not been used in the tunnel table, that is the result of reversing the display icp. The visual color is not reversed - only the icon is reversed. As you can see in Table 16-1, 20 standard reserved colors located at the top and bottom of the system tangle, so that the results of bitmap mapping operations are still normal. However, once you start modifying the color panel - especially replacing the reserved color - then the bitmap operation of the color object becomes meaningless.
The only guarantee is that the bitmap operation will operate in black and white. Black is the first item in the system palette (all of the icons are set to 0), while the white is the final item (all of the primitive elements are set to 1). These two projects cannot be changed. If you need to predict the result of the bitmap operation on the color object, you can get the system tag table, then view the RGB color value of the different iconic value.
View the system palette
The program executed under Windows will process the logical tuning disk, and better serve the logical color panel to all the programs that use the logical color panel, Windows will set the color in the system tuning. The system palette replicates the hardware comparison table of the display card. In this way, check the system palette helps to adjust the color dish application.
Because there are three different ways to handle this problem, I will show you three programs to display the contents of the system color panel.
Syspal1 program, as shown in the formula 16-4, using the getSystemPaletteenTries in the previously described.
Co-style 16-4 syspal1syspal1.c / * ----------------------------------------- ---------------------------------- Syspal1.c - Displays System Palette (C) Charles Petzold, 1998- -------------------------------------------------- -------------------------- /
#include
Lresult Callback WndProc (HWND, UINT, WPARAM, LPARAM);
Tchar szappname [] = text ("syspal1");
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {HWND hwnd; MSG msg; WNDCLASS wndclass; wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor (NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); wndclass.lpszMenuName = NULL; wndclass. lpszClassName = szAppName; if {MessageBox (NULL, TEXT ( "This program requires Windows NT!"), szAppName, MB_ICONERROR); return 0;} (RegisterClass (& wndclass)!) hwnd = CreateWindow (szAppName, TEXT ( "System Palette # 1 "), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); if (hwnd) return 0;! ShowWindow (hwnd, iCmdShow); UpdateWindow (hwnd);
While (GetMessage (& MSG, NULL, 0, 0)) {TranslateMessage (& MSG); DispatchMessage (& MSG);} return msg.wparam;}
Bool CheckdisPlay (HWND HWND) {HDC HDC; INT IPALSIZE
HDC = Getdc (hwnd); ipalsize = getDeviceCaps (HDC, SizePalette); ReleaseDC (HWND, HDC);
if (! iPalSize = 256) {MessageBox (hwnd, TEXT ( "This program requires that the video") TEXT ( "display mode have a 256-color palette."), szAppName, MB_ICONERROR); return FALSE;} return TRUE; }
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {static int cxClient, cyClient; static SIZE sizeChar; HDC hdc; HPALETTE hPalette; int i, x, y; PAINTSTRUCT ps; PALETTEENTRY pe [256]; TCHAR SZBuffer [16];
switch (message) {case WM_CREATE: if (CheckDisplay (hwnd)!) return -1; hdc = GetDC (hwnd); SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)); GetTextExtentPoint32 (hdc, TEXT ( "FF-FF-FF" ), 10, & zechar); ReleaseDC (HWnd, HDC); RETURN 0; Case WM_DisplayChange: if (! Checkdisplay (HWND)) DestroyWindow (hwnd); Return 0;
Case WM_SIZE: CXClient = loword (lparam); cyclient = HiWord (LPARAM); Return 0;
Case WM_Paint: HDC = Beginpaint (HWND, & PS); SelectObject (HDC, getStockObject (system_fixed_font));
GetSystempaletteentries (HDC, 0, 256, PE);
For (i = 0, x = 0, y = 0; i <256; i ) {wsprintf (szbuffer, text ("% 02x-% 02x-% 02x"), PE [i] .pled, pe [i] .pegreen, pe [i] .peblue);
TextOut (HDC, X, Y, Szbuffer, Lstrlen (Szbuffer);
IF ((x = sizechar.cx) sizechar.cx> cxclient) {x = 0; if ((y = sizechar.cy)> cyclient) Break;}} Endpaint (hwnd, & ps); Return 0;
Case WM_Palettechanged: InvalidateRect (HWND, NULL, FALSE); RETURN 0;
Case WM_DESTROY: PostquitMessage (0); Return 0;} Return DEFWINDOWPROC (HWND, Message, WPARAM, LPARAM);} As with other programs in the Syspal series, unless the getDeviceCaps return value with the SizePalette parameter is 256, otherwise syspal1 is not Will execute.
Note that it is invalid regardless of the WM_PALETTECHANGED message from the display area of syspal1. During the merge WM_PAINT message processing, Syspal1 calls GetSystemPaletteentries and uses an array containing 256 PaletTeentry structures as a parameter. The RGB value is displayed as a text string in the display area. When executed, pay attention to 20 reserved colors is the top 10 and after 10 in the RGB value list, which is the same as those shown in Table 16-1.
When Syspal1 displays useful information, it is different from the actual 256 colors. That is the job of syspal2, as shown in the formula 16-5.
Co-style 16-5 syspal2syspal2.c / * ----------------------------------------- ---------------------------------- SYSPAL2.C - Displays System Palette (C) Charles Petzold, 1998- -------------------------------------------------- ------------------------- * / # include
Lresult Callback WndProc (HWND, UINT, WPARAM, LPARAM);
Tchar szappname [] = text ("syspal2");
Int WinApi Winmain (Hinstance Hinstance, Pstr Szcmdline, int icmdshow) {hwnd hwnd; msg msg; WNDCLASS WNDCLASS;
wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor (NULL , IDC_ARROW); wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szAppName;! if (RegisterClass (& wndclass)) {MessageBox (NULL, TEXT ( "This program requires Windows NT! "), szAppName, MB_ICONERROR); return 0;} hwnd = CreateWindow (szAppName, TEXT (" System Palette # 2 "), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); if (! HWND) RETURN 0; ShowWindow (hwnd, icmdshow); UpdateWindow (HWND);
While (GetMessage (& MSG, NULL, 0, 0)) {TranslateMessage (& MSG); DispatchMessage (& MSG);} return msg.wparam;}
Bool CheckdisPlay (HWND HWND) {HDC HDC; INT IPALSIZE
HDC = Getdc (hwnd); ipalsize = getDeviceCaps (HDC, SizePalette); ReleaseDC (HWND, HDC);
if (! iPalSize = 256) {MessageBox (hwnd, TEXT ( "This program requires that the video") TEXT ( "display mode have a 256-color palette."), szAppName, MB_ICONERROR); return FALSE;} return TRUE; } LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {static HPALETTE hPalette; static int cxClient, cyClient; HBRUSH hBrush; HDC hdc; int i, x, y; LOGPALETTE * plp; PAINTSTRUCT ps; RECT rect ;
Switch (message) {copy wm_create: if (! Checkdisplay (hwnd)) Return -1;
PLP = Malloc (SizeOf (Logpalette) 255 * Sizeof (PaletteEntry);
PLP-> Palversion = 0x0300; PLP-> PALNUMENTRIES = 256;
For (i = 0; i <256; i ) {plp-> palpalentry [i] .plent = i; plp-> palpalent [i] .pegreen = 0; plp-> palpalent [i] .peblue = 0; PLP -> palpalentry [i] .peflags = pc_explicit;} HPALETTE = CreatePalette (PLP); Free (PLP); Case WM_DisplayChange: if (! checkdisplay (hwnd) DESTROYWINDOW (HWND);
Return 0;
Case WM_SIZE: CXClient = loword (lparam); cyclient = HiWord (LPARAM); Return 0;
Case WM_Paint: HDC = BeginPaint (HWND, & PS);
SelectPalette (HDC, HPALETTE, FALSE); REALIZEPALETTE (HDC);
For (y = 0; y <16; y ) for (x = 0; x <16; x ) {hbrush = createsolidbrush (PaletteIndex (16 * y x)); setRect (& Rect, x * cxclient / 16, y * Cyclient / 16, (x 1) `* cxclient / 16, (Y 1) * cyclient / 16); FillRect (HDC, & Rect, Hbrush); deleteObject (hbrush);} Endpaint (hwnd, & ps); Return 0;
Case WM_PALETTECHANGED: IF ((hwnd) WPARAM! = HWND) InvalidateRect (HWND, NULL, FALSE);
Return 0;
Case WM_DESTROY: DeleteObject (HPALETTE); PostquitMessage (0); Return 0;} Return DEFWINDOWPROC (HWND, Message, WPARAM, LPARAM);} Syspal2 establishes a logical tunnel during WM_CREATE message processing. But please note: All 256 values in the logical palette are from 0 to 255 color palette, and the Peflags field is PC_EXPLICIT. The flag is defined in this: "The lower class of the logical palette item specifies a hard body color palette index. This flag allows the application to display the content of the hard-moving tray." The flag is special Designed for this thing we have to do. During WM_PAINT message processing, Syspal2 selects the toner disk into the content of the device and presents it. This does not cause any restructuring of the system color tray, but allow program to use the PaletteIndex gauge to specify the color in the system palette. According to this method, Syspal2 shows 256 rectangles. In addition, when you perform this program, pay attention to the top 10 and then 10 colors of the top row and the bottom row are 20 reserved colors, as shown in Table 16-1. When you perform the program that uses your own logical paper, the display changes.
If you like to look at the color in syspal2, you like the value of RGB, then do it simultaneously with the WhatCLR program in Chapter 8.
The technology used in the SYSPAL series has recently appeared in me - from I started working for more than seven years from the Windows Toner Manager, there were only those technologies.
In fact, all GDI functions specify the color as the RGB value directly or indirectly. Inside the GDI, this will be converted to a primitive element associated with that color. These conversions are quite directly in some display modes (eg, 16-bit or 24-bit color mode). In other display modes (4-bit or 8-bit color), this may involve a search closest to color.
However, there are two GDI letters to let you specify the color in the status of the status. Of course, these two functions used in this way are highly related to the device. They are too dependent on the device, so that they can directly display the actual palette comparison table on the video display card. These two functions are Bitblt and StretchBLT.
The SYSPAL3 program shown in the formula 16-6 displays a method of displaying the color of the system palette using the Stretchblt.
Code 16-6 Syspal3Syspal3.c / * ----------------------------------------- ---------------------------------- Syspal3.c - Displays System Palette (C) Charles Petzold, 1998- -------------------------------------------------- ------------------------- * /
#include
wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor (NULL , IDC_ARROW); wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szAppName;! if (RegisterClass (& wndclass)) {MessageBox (NULL, TEXT ( "This program requires Windows NT! "), szAppName, MB_ICONERROR); return 0;} hwnd = CreateWindow (szAppName, TEXT (" System Palette # 3 "), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
IF (! hwnd) returnography; showwindow (hwnd, icmdshow); UpdateWindow (HWND);
While (GetMessage (& MSG, NULL, 0, 0)) {TranslateMessage (& MSG); DispatchMessage (& MSG);} return msg.wparam;}
Bool CheckdisPlay (HWND HWND) {HDC HDC; INT IPALSIZE
HDC = Getdc (hwnd); ipalsize = getDeviceCaps (HDC, SizePalette); ReleaseDC (HWND, HDC);
if (! iPalSize = 256) {MessageBox (hwnd, TEXT ( "This program requires that the video") TEXT ( "display mode have a 256-color palette."), szAppName, MB_ICONERROR); return FALSE;} return TRUE; }
LRESULT CALLBACK WNDPROC (HWND HWND, UINT MESSAGE, WPARAM WPARAM, LPARAM LPARAM) {Static Hbitmap HbitMap; Static Int CxClient, Cyclient; Byte Bits [256]; HDC HDC, HDCMEM; INT I; PAINTSTRUCT PS
Switch (message) {copy wm_create: if (! Checkdisplay (hwnd)) Return -1;
For (i = 0; i <256; i ) bits [i] = i; hbitmap = createBitmap (16, 16, 1, 8, & bits); Return 0; Case WM_DisplayChange: if (! Checkdisplay (hwnd)) DestroyWindow HWND); RETURN 0;
Case WM_SIZE: CXClient = loword (lparam); cyclient = HiWord (LPARAM); Return 0;
Case WM_Paint: HDC = BeginPaint (HWND, & PS);
HDCMEM = CREATECOMPATIPLEDC (HDC); SELECTOBJECT (HDCMEM, HBitmap);
Stretchblt (HDC, 0, 0, CxClient, Cyclient, HDCMEM, 0, 0, 16, 16, SRCCOPY);
DeleteDC (hdcMem); EndPaint (hwnd, & ps); return 0; case WM_DESTROY: DeleteObject (hBitmap); PostQuitMessage (0); return 0;} return DefWindowProc (hwnd, message, wParam, lParam);} during WM_CREATE Messaging SYSPAL3 uses createBitMap to establish a dot matrix of 8-bit metaps per status of 16 × 16. The last parameter of the function is a 256-bit component array including a value of 0 to 255. These are 256 possible icon metad values. In the program that handles the WM_Paint message, the program selects this dot mapping to the content of the memory device, displayed with StretchBLT and populates the display area. Windows only transmits the icons in the dot mapping to the hard body of the video display, allowing these icons to deposit 256 items in the color disc comparison table. Program display area does not have to make the received WM_PALETTECHANGED message ineffective - any modifications to the comparison table affect the display of Syspal3.
Palette animation
The word "animation" is seen in the title of this section, and the "computer pet" executed around the screen will be considering the "computer Pet" performed around your eyes. Yes, you can use the Windows Toner Manager to make some animations, and there is a certain animation.
Typically, the animation under Windows is to quickly continuously display a series of dot mapping. Palette animations have a big difference with this method. You can start everything you need on the screen, then you process the color palette to change the color of these objects, it may be an image that is not visible to the background of the screen. You can get an animation effect without using this method without having to call anything. The speed of the palette animation is quite fast.
For the movie animation, the initial establishment work is some different from us: for each RGB color value to modify during the animation, the PEFLAGS field of the PaletteEntry structure must be set to PC_RESERVED.
Usually, as we see, you set the peflags tag to zero when establishing a logical paper disc. This allows GDI to map the same colors in multiple logical color trays to the same system palette item. For example, assume that two Windows programs have established a logical tuning discs containing RGB items 10-10-10, then Windows requires only one 10-10-10 project in the system tag table. But if you use a palette animation in these two programs, then you don't let GDI use a palette. Palette animation means that the speed is very fast - and it is only possible to increase the speed if it is not re-painted. When modifying the color dish using a palette animation, it does not affect other programs, or forces the GDI restructuring system to draw a table. PC_RESERVED's PEFLAGS value is a single logical color panel storage system palette item. When using a palette movie, you can usually call SelectPalette and RealizePalette during WM_PAINT message processing, and use the PaletteIndex gauge to specify the color. This gauge will bring an index into a logical tag table.
For animations, you may have to respond to WM_Timer messages by changing the color dish. To change the RGB color value in the logical palette, use a PaletteEntry array to call the Function AnimatePalette. This file is very fast because it only needs to change the system tuning disk and the project in the display card hardware palette table.
Beat the ball
Cheng Ti16-7 shows the BOUNCE element, but there is a program that can show the ball. For the sake of simplicity, the ball is drawn into an ellipse according to the size of the display area. Because this chapter has several palette movies, the Palanim.c ("Pattern Animation") file contains some general content.
Program 16-7 Bouncepalanim.c / * ----------------------------------------- --------------------------------- Palanim.c - Palette Animation Shell Programs (C) Charles Petzold, 1998- -------------------------------------------------- ------------------------ * /
#include
LResult Callba CK WndProc (HWND, UINT, WPARAM, LPARAM);
Extern tchar szappname []; extern tchar sztitle [];
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {HWND hwnd; MSG msg; WNDCLASS wndclass; wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor (NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); wndclass.lpszMenuName = NULL; wndclass. lpszClassName = szAppName; (! RegisterClass (& wndclass)) if {MessageBox (NULL, TEXT ( "This program requires Windows NT!"), szAppName, MB_ICONERROR); return 0;} hwnd = CreateWindow (szAppName, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, HINSTANCE, NULL; if (! Hwnd) return 0; showwindow (hwnd, icmdshow); UpdateWindow (HWND);
While (GetMessage (& MSG, NULL, 0, 0)) {TranslateMessage (& MSG); DispatchMessage (& MSG);} return msg.wparam;}
Bool CheckdisPlay (HWND HWND) {HDC HDC; INT IPALSIZE
HDC = Getdc (hwnd); ipalsize = getDeviceCaps (HDC, SizePalette); ReleaseDC (HWND, HDC);
if (! iPalSize = 256) {MessageBox (hwnd, TEXT ( "This program requires that the video") TEXT ( "display mode have a 256-color palette."), szAppName, MB_ICONERROR); return FALSE;} return TRUE; }
LRESULT CALLBACK WNDPROC (HWND HWND, UINT MESSAGE, WPARAM WPARAM, LPARAM LPARAM) {Static HPALETTE HPALETTE; Static Int CxClient, Cyclient; HDC HDC; PaintStruct PS
Switch (message) {copy wm_create: if (! Checkdisplay (hwnd)) Return -1;
HPALETTE = CREATEROUTINE (HWND); RETURN 0; Case WM_DisplayChange: if (! Checkdisplay (hwnd)) DestroyWindow (HWND); Return 0;
Case WM_SIZE: CXClient = loword (lparam); cyclient = HiWord (LPARAM); Return 0;
Case WM_Paint: HDC = BeginPaint (HWND, & PS);
SelectPalette (HDC, HPALETTE, FALSE); REALIZEPALETTE (HDC);
PainTroutine (HDC, CXClient, Cyclient);
Endpaint (hwnd, & ps); Return 0; Case WM_TIMER: HDC = GetDC (HWND);
SelectPalette (HDC, HPALETTE, FALSE);
Timerroutine (HDC, HPALETTE);
ReleaseDC (HWND, HDC); RETURN 0;
Case WM_QUERYNEWPALETTE: IF (! hpalette) Return False;
HDC = Getdc (HWND); SelectPalette (HDC, HPALETTE, FALSE); RealizePalette (HDC); InvalidateERECT (HWND, NULL, TRUE);
ReleaseDC (HWND, HDC); Return True;
Case WM_PALETTECHANGED: IF (! hpalette || (hwnd) wparam == hwnd) Break;
HDC = getDC (hwnd); SelectPalette (HDC, HPALETTE, FALSE); RealizePalette (HDC); UpdateColors (HDC);
ReleaseDC (HWND, HDC); Break;
Case WM_DESTROY: DESTROYROUTINE (HWND, HPALETTE); PostquitMessage (0); Return 0;} Return DEFWINDOWPROC (Hwnd, Message, WPARM, LPARAM);} bounce.c / * ------------ -------------------------------------------------- ----------- Bounce.c - Palette Animation Demo (C) Charles Petzold, 1998 ------------------------ -------------------------------------------------- - * /
#include
Static logpalette * plp; hpalette createroutine (hwnd hwnd) {HPALETTE HPALETTE; INT i;
PLP = Malloc (SizeOf (Logpalette) 33 * Sizeof (Paletteentry)); PLP-> PALVERSION = 0x0300; PLP-> PalNumentries = 34;
For (i = 0; i <34; i ) {plp-> palpalent [i] .plentry = 255; plp-> palpalent [i] .pegreen = (i == 0? 0: 255); plp-> palpalentry [i] .peblue = (i == 0? 0: 255); plp-> palpalent [i] .peflags = (i == 33? 0: pc_reserved);} HPALETTE = CREATEPALETTE (PLP); setTimer (hwnd, ID_TIMER, 50, NULL); return hPalette;} void PaintRoutine (HDC hdc, int cxClient, int cyClient) {HBRUSH hBrush; int i, x1, x2, y1, y2; RECT rect; // Draw window background using palette index 33
SetRect (& Rect, 0, 0, CxClient, Cyclient); Hbrush = Createsolidbrush (PaletteIndex (33)); FillRect (HDC, & Rect, Hbrush); deleteObject (Hbrush);
// Draw the 33 BallsselectObject (HDC, getStockObject (null_pen)); for (i = 0; i <33; i ) {x1 = i * cxclient / 33; x2 = (i 1) * cxclient / 33;
IF (i <9) {y1 = i * cyclient / 9; Y2 = (i 1) * cyclient / 9;} else if (i <17) {y1 = (16 - i) * cyclient / 9; y2 = (17 - i) * cyclient / 9;} else if (i- 25) {y1 = (i - 16) * cyclient / 9; y2 = (i - 15) * cyclient / 9;} else {y1 = (32 - i) * cyclient / 9; y2 = (33 - i) * cyclient / 9;}
hBrush = CreateSolidBrush (PALETTEINDEX (i)); SelectObject (hdc, hBrush); Ellipse (hdc, x1, y1, x2, y2); DeleteObject (SelectObject (hdc, GetStockObject (WHITE_BRUSH)));} return;}
Void Timerroutine (HDC HDC, HPALETTE HPALETTE) {static bool blefttoright = true; static int iball;
// set old ball to whiteplp-> palpalent [iball] .pegreen = 255; plp-> palpalent [iball] .peblue = 255;
Iball = (BLEFTTORHT? 1: -1); if (iball == (BLEFTTORHT? 33: -1)) {iball = (BLEFTTORHT? 31: 1); blefttoright ^ = true;} // set new ball to red
PLP-> palpalentry [iball] .pegreen = 0; PLP-> PALPALENTRY [IBALL] .peblue = 0;
// Animate the Palette
AnimatePalette (HPALETTE, 0, 33, PLP-> PALPALENTRY); RETURN;}
Void DestroyRoutine (HWND HWND, HPALETTE HPALETTE) {KillTimer; deleteObject (HPALETTE); Free (PLP); Return;} If Windows is in the display mode of the support toner, it will not be able to jobs. Therefore, Palanim.c starts processing WM_CREATE by calling the Checkdisplay function (same as the form in the Syspal).
Palanim.c Call Four Versions in Bounce.c: Call CREATEROUTINE during WM_CREATE message processing (used to establish a logical color display in Bounce); call PainTroutine during WM_PAINT message processing; call TimerRoutine during WM_TIMER message processing; Call DestroyRoutine during WM_DESTROY message processing (for clearing in Bounce). Before calling PainTroutine and TimerRoutine, Palanim.c obtains the contents of the device and selects it to logical paper. Before calling PainTroutine, it also appears a palette. Palanim.c expects Timerroutine call animatepalette. Although AnimatePalette needs to select a palette from the device content, it does not need to call RealizePalette.
The ball in Bounce is hopped back and forth in the display area in the "W" route. The display area background is white, the ball is red. At any time, you can see the ball in one of 33 non-overlapping locations. This requires 34 color disc items: a ball for background, other 33 for different locations. In Createroutine, Bouncentry is initialized an array of PaletteEntry structures, set the first tuning disk item (corresponding to the position of the ball in the upper left corner) to red, and the other settings are white. Note that all items other than the background are set to PC_RESERVED (the background is the last palette item). Bounce terminates CreateRoutine by setting the interval between Windows timers to 50 milliseconds.
Bounce completed all painting work in PainTroutine. The window background is drawn with a colors specified by a solid painted brush and a toner profile 33. The color of 33 balls is based on the color of the color panel index from 0 to 32. When Bounce first draws in the display area, the color palette is mapped to red, and the other color palettes are mapped to the white. This causes the ball to appear in the upper left corner.
When WndProc processes WM_TIMER messages and calls TimerRoutine, the animation happens. TimerRoutine ends by calling animatePalette, the syntax is as follows:
AnimatePalette (HPALETTE, USTART, UNUM, & PE); where the first parameter is a palette representation, the last parameter is an indicator of the array, which consists of one or more PaletTeentry structures. This function changes several items from the USTART project to the UNUM project in the logical paper. The new USTART project in the logical color tray is the first member in the PaletteEntry structure. Beware! The uStart parameter is an index of the original logical tag, not the index of the PaletteEntry array. For convenience, BOUNCE uses the array of PaletteEntry structures that is part of the LogPalette structure used when establishing a logical color tray. The current location of the ball (from 0 to 32) is stored in static variable IBALL. During TimerRoutine, Bounce sets the PaletteEntry member to white. Then, the next position of the ball is then calculated, and the element is set to red. Use the following call to change the contrast:
AnimatePalette (HPALETTTE, 0, 33, PLP-> PALPALENTRY); GDI change 33 logical color palette item (although only two only), make it associated with changes in the system tag table Correspondence, then modify the hardware tag table on the display card. In this way, you don't have to move the ball.
When Bounce is executed, you will find that the effect of executing Syspal2 or Syspal3 will be better.
Although AnimatePalette is implemented very fast, you should try to avoid changing all logical palette items when only one or two project changes. This is a bit complicated in Bounce, because the ball is going back and forth. One method is to use two varies: referred to as Iballold, respectively, and iBallmin (iBall, and Iballold). Then you can call animatePalette like this to change two projects:
Iballmin = min (iball, iballold); AnimatePalette (HPAL, IBALLMIN, 2, PLP-> PALPALETRY IBALLMIN); there is another method: We first assume that you define a PaletteEntry structure:
PaletteEntry PE; During TimerRoutine, you set the PaletteEntry field to white and call animatePalette to change a project in the IBALL location in the logical color panel:
Pe.PEGREEN = 255; pe.peblue = 255; pe.peflags = pc_reserved; AnimatePalette (HPALETTE, IBALL, 1, & PE); then calculate the new value of IBALL displayed in Bounce, put the PaletTeentry structure The field is defined as red, then call animatePalette again:
PE.PEGREEN = 0; pe.peblue = 0; pe.peflags = pc_reserved; AnimatePalette (HPalette, Iball, 1, & PE); Although the ball is a traditional brief description of animation, It is actually not suitable for palette animations because all possible positions of the ball must be drawn first. The palette animation is more suitable for displaying a repeating pattern of motion.
Palemete animation of a project
One more interesting aspects in the palette animation is that only one palette item is used to complete some interesting technologies. For example, the FADER program shown in the formula 16-8. This program also requires the previous Palanim.c file. Cheng 16-8 Faderfader.c / * ----------------------------------------- -------------------------------- Fader.c - Palette Animation Demo (C) Charles Petzold, 1998 - -------------------------------------------------- ---------------------- * /
#include
Static logpalette lp; hPALETTE CREATEROUTINE (HPALETTE HPALETTE; lp.palversion = 0x0300; lp.palNumentries = 1; lp.palpalent [0] .pered = 255; lp.palpalentry [0] .pegreen = 255; lp. Palpalentry [0] .peblue = 255; lp.palpalent [0] .peflags = pc_reserved; hpalette = createpalette (& lp); setTimer (hwnd, id_timer, 50, null); return hpalette;}
Void PainTroutine (HDC HDC, INT CXClient, int Cyclient) {static tchar sztext [] = text ("fade in and out"); int x, y; size sizetext;
SetTextColor (HDC, PaletteIndex (0)); GetTextExtentPoint32 (HDC, Sztext, Lstrlen (Sztext), & SizeText);
For (x = 0; x Return;} Void TimerRoutine (HDC HDC, HPALETTE HPALETTTE) {static bool bfadein = true; if (bfadein) {lp.palpalentry [0] .pered - = 4; lp.palpalentry [0] .pegreen - = 4; IF (lp.palpalent [0] .pered == 3) bfadein = false;} else {lp.palpalent [0] .pered = 4; lp.palpalentry [0] .pegreen = 4; IF (lp.palpalent [0] .pered == 255) bfadein = true; AnimatePalette (HPALETTE, 0, 1, LP.PALPALENTRY); RETURN;} Void DestroyRoutine (HWND HWND, HPALETTE HPALETTE) {KillTimer (hwnd, id_timer); deleteObject (HPALETTE); RETURN;} FADER displays full text string "Fade In and Out" on the display area. The text is first displayed on white, which is not seen on the window of the white background. By using a palette animation, Fader slowly change the color of the text to blue, then change it back, repeating it over and over again. The text has a gradual display effect. Fader establishes a logical color tray with the CreateRoutine function, which only needs a palette item and initializes the color to white-red, green and blue values to 255. In PainTroutine (you may think of, when the logical color panel is selected into the device content and appear, the Palanim call over this function), the Fader call setTextColor sets the text color to PaletteIndex (0). This means that the text color is set to the first project in the palette table, which is initially white. The Fader then populates the display area with the "Fade In and Out" text string. At this time, the window background is white, the text is also white, so the text is invisible. In the TimerRoutine function, Fader completes the palette animation by changing the PaletteEntry structure and passes it to AnimatePalette. Initially, it is reduced to each WM_TIMER message, and the preparation will be reduced by 4 until it is equal to 3; then adds these values 4 until it is equal to 255. This will make the text color gradually change from the white to blue, then back to white. The AllColor programs shown in the formula 16-9 only use a project of the logical color panel to display all the colors that the display card can be colored. Of course, the program is not displayed simultaneously, but continuously displayed. If the display card has 18-bit resolution (at this time, there can be 262144 different colors), then you can see all the colors on the screen at a speed of 55 milliseconds in two color spacing. Cheng --------------------------------------------------------------------------------------------------------------- ---------------------------------- AllColor.c - Palette Animation Demo (C) Charles Petzold, 1998- -------------------------------------------------- -------------------------- / #include Tchar szappname [] = text ("allcolor"); tchar sztitle [] = text ("AllColor: Palette Animation Demo); Static INT IINCR; Static Paletteentry PE; HPALETTE CREATEROUTINE (HWND HWND) {HDC HDC; HPALETTE HPALETTE; LOGPALETTE LP; // determine the color resolution and set Iincrhdc = getdc (hwnd); IINCR = 1 << (8 - getDeviceCaps (HDC, ColorRES) / 3); ReleaseDC (HWND, HDC); // create the logical pastetelp.palversion = 0x0300; lp.palNumentries = 1; lp.palpalent [0] .pered = 0; lp.palpalent [0] .pegreen = 0; lp.palpalent [0] .peblue = 0; lp.palPalEntry [0] .peFlags = PC_RESERVED; hPalette = CreatePalette (& lp); // Save global for less typingpe = lp.palPalEntry [0]; SetTimer (hwnd, ID_TIMER, 10, NULL); return hPalette;} void DisplayRGB (HDC HDC, PALETTEENTRY * PPE) {Tchar Szbuffer [16]; WSPrintf (Szbuffer, Text ("% 02x-% 02x-% 02x"), PPE-> Pred, Ppe-> Pegreen, PPE-> peblue; Textout (HDC, 0, 0, SZBuffer, Lstrlen (szbuffer); Void PainTroutine (HDC HDC, INT CXCLIENT, INT CYCLIENT) {Hbrush Hbrush; Rect RECT // Draw Palette INDEX 0 on Entire Window hBrush = CreateSolidBrush (PALETTEINDEX (0)); SetRect (& rect, 0, 0, cxClient, cyClient); FillRect (hdc, & rect, hBrush); DeleteObject (SelectObject (hdc, GetStockObject (WHITE_BRUSH))); // Display the RGB ValuedisplayRGB (HDC, & PE); Return; void TimerRoutine (HDC hdc, HPALETTE hPalette) {static BOOL bRedUp = TRUE, bGreenUp = TRUE, bBlueUp = TRUE; // Define new color valuepe.peBlue = (bBlueUp iIncr:? -iIncr); if (pe.peBlue == (Byte) (BBLUEUP? 0: 256 - IINCR)) {pe.peblue = (BBLUEUP? 256 - IINCR: 0); BBLUEUP ^ = true; pe.pegreen = (bgreenup? Iincr: -IinCr); IF (PE.PEGREEN == (Byte) (BGreenup? 0: 256 - IINCR)) {pe.pegreen = (bgreenup? 256 - Iincr: 0); bgreenup ^ = true; pe.pered = (Bredup? IINCR: -IINCR); IF (PE.PERED == (Byte) (Bredup? 0: 256 - IINCR)) {pe.pered = (BREDUP? 256 - IINCR: 0); bredup ^ = true;}}} // Animate the paletteAnimatePalette (hPalette, 0, 1, & pe); DisplayRGB (hdc, & pe); return;} void DestroyRoutine (HWND hwnd, HPALETTE hPalette) {KillTimer (hwnd, ID_TIMER); DeleteObject (hPalette); return;} On the structure, AllColor is very similar to the Fader. In CreateRoutine, AllColor establishes a colorish disk with a black toner item (the Red, Green and Blue fields of the PaletteEntry structure). In PainTroutine, AllColor establishes solid paintings with PaletteIndex (0), and calls FillRect to color with this painting. In TimerRoutine, AllColor launches the color tray by changing the PaletteEntry color and calls AnimatePalette. I have written allColor programs so that the color changes smooth. First, the blue value gradually increases. When the maximum is reached, the green value increases, and the blue value is gradually reduced. The increase and decrease in red, green and blue values depends on the IInCr variable. During CREATEROUTINE, this will calculate according to the value returned from getDeviceCaps with the colorres parameter. For example, if getDevicecaps are transmitted back 18, then IINCR is set to 4 - a minimum of all colors. AllColor is still displaying the current RGB color value in the upper left corner of the display area. I originally added this program code for test purposes, but now prove it is useful, so I keep it. Engineering application In engineering applications, animations are useful for displaying mechanical or electricity. The internal combustion engine is displayed on the computer screen, but the animation can make it more vivid and clearly display its work procedures. A good example of using a palette movie is the process of displaying fluid through the pipe. This is an example, the image does not have to be very accurate - in fact, if the image is very accurate (just like a transparent pipe), it is difficult to explain how the fluid in the tube moves. At this time, the symbol will be better. The PIPES program shown in the formula 16-10 is a simple demonstration of this technology: there are two horizontal tubes in the display area, and the fluid flows from left to right in the upper tube, and moves from right to the right below. Code 16-10 Pipes Pipes.c / * ------------------------------------------- ---------------------------- Pipes.c - Palette Animation Demo (C) Charles Petzold, 1998 ------- -------------------------------------------------- ------------------ * / #include Static logpalette * PLP; HPALETTE CREATEROUTINE (HPALETTE HPALETTE; INT i; PLP = Malloc (Sizeof (Logpalette) 32 * Sizeof (Paletteentry)); // Initialize The Fields of the LogPalette StructurePLP-> PALVERSION = 0x300; PLP-> PALNUMENTRIES = 16; for (i = 0; i <= 8; i ) {plp-> palpalent [i] .pered = (byte) min (255, 0x20 * i); plp-> palpalent [i] .pegreen = 0; plp-> palpalent [i] .peblue = (Byte) MIN (255, 0x20 * i); plp-> palpalentry [i] .peflags = pc_reserved; PLP-> PALPALENTRY [16 - I] = PLP-> Palpalent [i]; plp-> palpalent [16 i] = plp-> palpalent [i]; plp-> palpalent [32 - i] = plp-> palpalentry [i]; HPALETTE = CREATEPALETTE (PLP); SetTimer (hwnd, id_timer, 100, null); return hPALETTE;} Void PainTroutine (HDC HDC, INT CXClient, INT CYCLIENT) {hbrush hbrush; int 网; recc // Draw Window Background SetRect (& Rect, 0, 0, CxClient, Cyclient); Hbrush = SelectObject (HDC, GetStockObject (White_brush); FillRect (HDC, & Rect, Hbrush); // Draw the interiors of the pipesfor (i = 0; i <128; i ) {hbrush = Createsolidbrush (PaletteIndex (I% 16)); SelectObject (HDC, HBrush); Rect.Left = (127 - i) * cxclient / 128; ZRECT.Right = (128 - i) * cxclient / 128; Rect.top = 4 * cyclient / 14; rect.bottom = 5 * cyclient / 14; FillRect (HDC, & Rect, Hbrush); Rect.Left = i * cxclient / 128; Rect.right = (i 1) * cxclient / 128; Rect.top = 9 * cyclient / 14; Rect.Bottom = 10 * cyclient / 14; FillRect (HDC, & Rect, Hbrush); DeleteObject (SelectObject (HDC, getStockObject (white_brush));} //Dc, 0, 4 * cyclient / 14, null); lineto (HDC, CXClient, 4 * cyclient / 14); MoveToex (HDC, 0, 5 * cyclient / 14, null); Lineto (HDC, CXClient, 5 * cyclient / 14); MoveToex (HDC, 0, 9 * cyclient / 14, null); lineto (HDC, CXClient, 9 * Cyclient / 14); MoveToex (HDC, 0, 10 * cyclient / 14, null); lineto (HDC, CXClient, 10 * cyclient / 14); return;} Void TimerRoutine (HDC HDC, HPALETTE HPALETTE) {Static Int Iindex; AnimatePalette (HPALETTE, 0, 16, PLP-> PALPALENTRY IINDEX); IINDEX = (IINDEX 1)% 16; Return;} Void DestroyRoutine (HWND HWND, HPALETTE HPALETTE) {KillTimer (HWND, ID_TIMER); DELETEOBJECT (HPALETTE); Free (PLP); Return;} PIPES uses 16 color panel items for animation, and you may use less project. When minimizing, there is a sufficient item to display the direction of the flow. It is better than using a static arrow with three palette projects. The Tunnel program shown in the formula 16-11 is the most greedous program in this group. It uses 128 color panel items for animation, but from the effect, it is worth doing. Co-style 16-11 tunneltunnel.c / * ----------------------------------------- ---------------------------------- Tunnel.c - Palette Animation Demo (C) Charles Petzold, 1998- -------------------------------------------------- ------------------------- * / #include Static logpalette * plp; hpalette createroutine (hwnd hwnd) {byte bygrayLevel; hPALETTE HPALETTE; INT i; PLP = Malloc (SizeOf (PaletteEntry); // Initialize The Fields of the Logpalette StructurePLP-> PALVERSION = 0x0300; PLP-> PALNUMENTRIES = 128; for (i = 0; i <128; i ) ) {IF (i <64) BYGRAYLEVEL = (Byte) (4 * i); elsebygracy = (byte) min (255, 4 * (128 - i))); PLP-> Palpalent [i] .pered = bygraylelevel; PLP -> palpalentry [i] .pegreen = bygrayLvel; PLP-> PALPALENTRY [I] .peblue = bygrayLvel; PLP-> PALPALENTRY [i] .peflags = pc_reserved; plp-> palpalentry [i 128] .pered = bygraylevel; PLP -> palpalentry [i 128] .pegreen = bygrayLevel; PLP-> Palpalent [i 128] .peblue = bygrayLvel; PLP-> Palpalent [i 128] .peflags = pc_reserved;} HPALETTE = CreatePalette (PLP); setTimer (hwnd, id_timer, 50, null); Return HPALETTE;} Void PainTroutine (HDC HDC, INT CXCLIENT, INT CYCLIENT) {Hbrush Hbrush; INT i; Rect Rect; for (i = 0; I <127; i ) {/ / Use a rect structure for Each of 128 RectanglesRect.Lep = i * cxclient / 255; Rect.top = i * cyclient / 255; Rect.right = CxClient - i * CX Client / 255; rect.bottom = cyClient - i * cyClient / 255; hBrush = CreateSolidBrush (PALETTEINDEX (i)); // Fill the rectangle and delete the brushFillRect (hdc, & rect, hBrush); (hBrush) DeleteObject;} return } Void TimerRoutine (HDC HDC, HPALETTE HPALETTE) {static int level; Ilevel = (Ilevel 1)% 128; AnimatePalette (HPALETTE, 0, 128, PLP-> PALPALENTRY ILVEL); Return;} Void DestroyRoutine (hwnd hwnd, hpalette hpalette) {killtimer (hwnd, id_timer); deleteObject (HPALETTE); Free (plp); Return;} Tunnel uses 64 moving grayscale in 128 color disc items - from black to White, then from white to black - performance in tunnel travel. Pamper and real world image Of course, even though we have completed many interesting things: continuously displaying the color of the color, do a palette animation, but the true purpose of the toner manager is to display the image in the real world in 8-bit display mode. . For the rest of this chapter, we just study. As you expect, when using the Packed Dib, GDI dot matrix objects and DIB blocks, you must use a palette in different ways. The six programs below clarify the various techniques for processing the dot matrix. Pamper and packed dib The following three programs help us establish a series of functions that handle the Packed Dib memory block. These functions are in the PackedIB file shown in the program 16-12. Co-style 16-12 PackedIB file packedib.h / * --------------------------------------- ---------------------------------- packedib.h - header file for packedib.c (c) Charles Petzold 1998 ------------------------------------------------ -------------------------- / #include BITMAPINFO * PackedDibLoad (PTSTR szFileName); int PackedDibGetWidth (BITMAPINFO * pPackedDib); int PackedDibGetHeight (BITMAPINFO * pPackedDib); int PackedDibGetBitCount (BITMAPINFO * pPackedDib); int PackedDibGetRowLength (BITMAPINFO * pPackedDib); int PackedDibGetInfoHeaderSize (BITMAPINFO * pPackedDib); int PackedDibGetColorsUsed (BITMAPINFO * pPackedDib); int PackedDibGetNumColors (BITMAPINFO * pPackedDib); int PackedDibGetColorTableSize (BITMAPINFO * pPackedDib); RGBQUAD * PackedDibGetColorTablePtr (BITMAPINFO * pPackedDib); RGBQUAD * PackedDibGetColorTableEntry (BITMAPINFO * pPackedDib, int i); BYTE * PackedDibGetBitsPtr (BITMAPINFO * pPackedDib ); int PackedDibgetBitsize (BitmapInfo * PPackedDib); HPALETTE PACKEDDIBCREATEPALETTE (BitMapInfo * PPackedDib); packedib.c / * --------------------------- ---------------------------------------------- Packedib.c - - Routines for Using Packed Dibs (C) Charles Petzold, 1998 ------------------------------------- ----------------------------------- --- * / # include / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------- PackedDibload: loading dib file as packed-dib memory block ------------ -------------------------------------------------- -------------- * / BITMAPINFO * PackedDibLoad (PTSTR szFileName) {BITMAPFILEHEADER bmfh; BITMAPINFO * pbmi; BOOL bSuccess; DWORD dwPackedDibSize, dwBytesRead; HANDLE hFile; // Open the file: read access, prohibit write access hFile = CreateFile (szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); if (hFile == INVALID_HANDLE_VALUE) return NULL; // Read in the BITMAPFILEHEADERbSuccess = ReadFile (hFile, & bmfh, sizeof (BITMAPFILEHEADER), & dwBytesRead, NULL ); if (! bsuccess || (dwbytesread!) || (BMFH.BFTYPE! = * (Word *) "BM")) {closeHandle (HFILE); Return Null;} // Allocate memory for the packed DIB & read it indwPackedDibSize = bmfh.bfSize - sizeof (BITMAPFILEHEADER); pbmi = malloc (dwPackedDibSize); bSuccess = ReadFile (hFile, pbmi, dwPackedDibSize, & dwBytesRead, NULL); CloseHandle (hFile); IF (! bsuccess || (dwbytesread! = dwpackedDibsize)) {free (pbmi); Return null;} Return PBMI; / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------- Functions to get information from Packed DIB ----------------- -------------------------------------------------- --------- * / int PackedDibGetWidth (BITMAPINFO * pPackedDib) {if (pPackedDib-> bmiHeader.biSize == sizeof (BITMAPCOREHEADER)) return ((PBITMAPCOREINFO) pPackedDib) -> bmciHeader.bcWidth; elsereturn pPackedDib-> bmiHeader.biWidth;} int PackedDibGetHeight (BITMAPINFO * pPackedDib) {if (pPackedDib-> bmiHeader.biSize == sizeof (BITMAPCOREHEADER)) return ((PBITMAPCOREINFO) pPackedDib) -> bmciHeader.bcHeight; elsereturn abs (pPackedDib-> bmiHeader.biHeight);} int PackedDibGetBitCount (BITMAPINFO * pPackedDib) {if (pPackedDib-> bmiHeader.biSize == sizeof (BITMAPCOREHEADER)) return ((PBITMAPCOREINFO) pPackedDib) -> bmciHeader.bcBitCount; elsereturn pPackedDib-> bmiHeader.biBitCount;} INT PACKEDDIBGETROWLENGTH (BitmapInfo * PPackedDib) {Return (PackedDibGetWidth * PackedDibgetBitcount (PPACKEDDIB) 31) & ~ 31) >> 3;} / * ---------------------------------------------------------------------------- -------------------------------------------------- -------- PackedDibgetinfoHeadersize Includes Possible Color Masks! --------------------------------- ----------------------------------------- * / int PackedDibGetInfoHeaderSize (BITMAPINFO * pPackedDib) {if (pPackedDib-> bmiHeader.biSize == sizeof (BITMAPCOREHEADER)) return ((PBITMAPCOREINFO) pPackedDib) -> bmciHeader.bcSize; else if (pPackedDib-> bmiHeader.biSize == sizeof (BITMAPINFOHEADER)) return pPackedDib-> bmiHeader.biSize (pPackedDib-> bmiHeader.biCompression == BI_BITFIELDS 12:? 0); else return pPackedDib-> bmiHeader.biSize;} / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------- PackedDibgetColorsused Returns Value in Information Header; COULD BE 0 To INDICATE NON-TRUNCATED Color Table! ------ -------------------------------------------------- -------------------- * / INT PACKEDDIBGETCOLORSUSED (PPACKEDDIB-> bmiheader.bisize == sizeof (bitmapcorehead)) Return 0; Elsereturn PPACKEDDIB-> bmiheader.biRused;} / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- PackedDibgetnumcolors Is Actual Number of Entries in Color Table ------------- -------------------------------------------------- -------------- * / int PackedDibGetNumColors (BITMAPINFO * pPackedDib) {int iNumColors; iNumColors = PackedDibGetColorsUsed (pPackedDib); if (iNumColors == 0 && PackedDibGetBitCount (pPackedDib) <16) iNumColors = 1 << PackedDibGetBitCount (pPackedDib); return iNumColors;} int PackedDibGetColorTableSize (BITMAPINFO * pPackedDib) {if (pPackedDib-> bmiHeader.biSize == sizeof (BITMAPCOREHEADER)) return PackedDibGetNumColors (pPackedDib) * sizeof (RGBTRIPLE); elsereturn PackedDibGetNumColors (pPackedDib) * sizeof (RGBQUAD);} RGBQUAD * PackedDibGetColorTablePtr (BITMAPINFO * pPackedDib) {if (PackedDibGetNumColors (pPackedDib) == 0) return 0; return (RGBQUAD *) (((BYTE *) pPackedDib) PackedDibGetInfoHeaderSize (pPackedDib));} RGBQUAD * PACKEDDIBGETCOLORTABERTRY (BitMapInfo * PPACKEDDIB, INT I) {IF (PackedDibGetNumcolors (PPACKEDDIB) == 0) Return 0; if (pPackedDib-> bmiHeader.biSize == sizeof (BITMAPCOREHEADER)) return (RGBQUAD *) (((RGBTRIPLE *) PackedDibGetColorTablePtr (pPackedDib)) i); elsereturn PackedDibGetColorTablePtr (pPackedDib) i;} / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ----------------------------------------------- -------------------------------------------------- ----- * / BYTE * PACKEDDIBGETBITSPTR (BitmapInfo * PPackedDib) {return ((byte *) PPACKEDDIB) PackedDibGetInfoHeadersize (PPACKEDDIB) PackedDibGetColortableSize (PPACKEDDIB); / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- PackedDibgetBitssesize Can Be Calculate from the Height and Row Lengthif It's Not Explicitly in The BisizeImage Field ---- -------------------------------------------------- ----------------------- * / int packedDibgetBitsSize (BitMapInfo * PPACKEDDIB) {ix ((ppackedDib-> bmiheader.bisize! = sizeof (bitmapcorehead) && (PPACKEDDIB-> Bmiheader.bisizeImage! = 0) Return PPACKEDDIB-> Bmiheader.bisizeImage; Return PackedDibgetHeight (PPACKEDDIB) * PackedDibGetRowLength (PPACKEDDIB); / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------- PackedDibcreatePalette Creates Logical Palette from PackedDIB ----------------- -------------------------------------------------- -------- * / HPALETTE PACKEDDIBCREATEPALETTTE PACKEDDIBCREATEPALETTE (BitMapInfo * PPACKEDDIB) {HPALETTE HPALETTE; INT I, INUMCOLORS; LOGPALETTE * PLP; RGBQUAD * PRGB; IF (0 == (Inumcolors = PackedDibgetnumcolors (PPACKEDDIB)) Return Null; PLP = Malloc (SizeOf (Inumcolors - 1) * SizeOf (PaletteEntry); plp-> palVersion = 0x0300; plp-> palNumEntries = iNumColors; for (i = 0; i HPALETTE = CREATEPALETTE (PLP); Free (PLP); Return HPALETTE;} The first one is PackedDibload, which will unique parameters as the archive name and pass back to the indicator of the Packed Dib in the memory. All other functions use this PACKED DIB index as their first parameters and return to information about DIB. These functions are arranged in the order in the order of "by the lower". Each function uses information from the previous one. I don't tend to say that this is a "full" card set when dealing with Packed Dib. Moreover, I don't want to compile a real extension, because I don't think this is a good way to deal with Packed Dib. You will obviously discover this in writing like the following: dwpixel = packedDibgetpixel (PPACKEDDIB, X, Y); this one includes too much nest-like card call, so that the efficiency is very low and very slow. This chapter will discuss a method I think is better. In addition, you will notice that many of these functions require DIBs with OS / 2 to take different handles; this, the function will frequently check if the first field of the BitmapInfo structure is the same as the BitMapCoreheader structure. . Pay special attention to the last function of PackedDibcreatePalette. This card uses a color table in DIB to create a tangle. If there is no color table in DIB (this means that each of the DIBs have 16, 24 or 32-bit yuan), then the color panel is not established. We sometimes refer to the color palette from the DIB color table as DIB's own palette. Packedib files are placed in ShowDIB3, as shown in the formula 16-13. Cheng-style 16-13 showdib3Showdib3.c / * ----------------------------------------- --------------------------------- Showdib3.c - Displays Dib with native Palette (c) Charles Petzold, 1998 -------------------------------------------------- -------------------------- / #include LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); TCHAR szAppName [] = TEXT ( "ShowDib3"); int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {HWND hwnd; MSG msg; WNDCLASS wndclass ; wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor (NULL , IDC_ARROW); wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); wndclass.lpszMenuName = szAppName; wndclass.lpszClassName = szAppName;! if (RegisterClass (& wndclass)) {MessageBox (NULL, TEXT ( "This program requires Windows NT! "), szappname, MB_ICONERROR); RETURN 0;} hwnd = CreateWindow (szAppName, TEXT ( "Show DIB # 3: Native Palette"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ShowWindow (hwnd, iCmdShow); UpdateWindow (hwnd); While (GetMessage (& MSG, NULL, 0, 0)) {TranslateMessage (& MSG); DispatchMessage (& MSG);} return msg.wparam;} LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {static BITMAPINFO * pPackedDib; static HPALETTE hPalette; static int cxClient, cyClient; static OPENFILENAME ofn; static TCHAR szFileName [MAX_PATH], szTitleName [MAX_PATH]; static TCHAR SZFILTER [] = text ("Bitmap Files (* .bmp) / 0*.bmp/0") Text ("All Files (*. *) / 0 *. * / 0/0"); HDC HDC; PaintStruct PS ; switch (message) {case WM_CREATE: ofn.lStructSize = sizeof (OPENFILENAME); ofn.hwndOwner = hwnd; ofn.hInstance = NULL; ofn.lpstrFilter = szFilter; ofn.lpstrCustomFilter = NULL; ofn.nMaxCustFilter = 0; ofn.nFilterIndex = 0; ofn.lpstrFile = szFileName; ofn.nMaxFile = MAX_PATH; ofn.lpstrFileTitle = szTitleName; ofn.nMaxFileTitle = MAX_PATH; ofn.lpstrInitialDir = NULL; ofn.lpstrTitle = NULL; ofn.Flags = 0; ofn.nFileOffset = 0 ; OFN.NFILEEXTENSION = 0; OFN.LPSTRDEFEXT = TEXT ("BMP"); OFN.LCUSTDATA = 0; OFN.LPFNHOOK = NULL; OFN.LPTEMPLATENAME = NULL; Return 0; Case WM_SIZE: CXClient = loword (lparam); cyclient = HiWord (LPARAM); Return 0; Case WM_Command: Switch (WPARAM) {CASE IDM_FILE_OPEN: // Show the file open dialog box IF (! getopenfilename (& off)) Return 0; // if there is an existing packed dib, free the memory if (pPackedDib) {free (pPackedDib); pPackedDib = NULL;} // If there's an existing logical palette, delete itif (hPalette) {DeleteObject (hPalette); hPalette = NULL;} // Load the packed DIB into memory SetCursor (LoadCursor (NULL, IDC_WAIT); showcursor (TRUE); PPACKEDDIB = PackedDibload (SZFileName); Showcursor (False); SetCursor (LoadCursor (NULL, IDC_ARROW); IF (PPACKEDDIB) {// Create The Palette from the Dib Color Table HPALETTE = PackedDibcreatePalette (PPACKEDDIB);} else {MessageBox (hwnd, text ("cannot loading dib file"), szappname, 0);} invalidateect (hwnd, null, true); Return 0;} Break; Case WM_Paint: HDC = BeginPaint (HWND, & PS); if (hPalette) {SelectPalette (hdc, hPalette, FALSE); RealizePalette (hdc);} if (pPackedDib) SetDIBitsToDevice (hdc, 0,0, PackedDibGetWidth (pPackedDib), PackedDibGetHeight (pPackedDib), 0,0,0, PackedDibGetHeight ( PpackedDib), PackedDibgetBitsptr (PpckedDib), PPACKEDDIB, DIB_RGB_COLORS; Endpaint (HWND, & PS); Return 0; Case WM_QUERYNEWPALETTE: IF (! hpalette) Return False; HDC = Getdc (HWND); SelectPalette (HDC, HPALETTE, FALSE); RealizePalette (HDC); InvalidateERECT (HWND, NULL, TRUE); ReleaseDC (HWND, HDC); Return True; Case WM_PALETTECHANGED: IF (! hpalette || (hwnd) wparam == hwnd) Break; HDC = getDC (hwnd); SelectPalette (HDC, HPALETTE, FALSE); RealizePalette (HDC); UpdateColors (HDC); ReleaseDC (HWND, HDC); Break; Case WM_DESTROY: IF (PPACKEDDIB) FREE (PPACKEDDIB); IF (HPALETTE) deleteObject (HPALETTE); PostQuitMessage (0); return 0;} return DefWindowProc (hwnd, message, wParam, lParam);} SHOWDIB3.RC (excerpt) // Microsoft Developer Studio generated resource script # include "resource.h" #include "afxres.h. "/// Menushowdib3 Menu Discardable Beginpopup" & File "BeginMenuItem" & Open ", IDM_FILE_OPENEndendResource.h (Explore) // Microsoft Developer Studio generated include file.// buy by showdib3.rc #define idm_file_open 40001ShowDIB3 Window message processing Program the PACKED DIB index as a static variable, and the window message processing is called this indicator during the "File Open" command. During this command, showdib3 also calls PackedDibcreatePalette to get a palette that may be used for DIB. Note that when Showdib3 is ready to load new DIB, you should first release the previous DIB memory and remove the previous DIB palette. In the program that processes the WM_DESTROY message, the last DIB finally released, the last color palette finally deleted. Processing the WM_PAINT message is simple: if there is a palette, showdib3 selects it into the device content and manipulate it. Then it calls setDibitStodevice and passes a file-related information (eg, the indicator of the width, high and pointing to the DIB icon), which is obtained from the functions in the PACKEDIB. Also, remember that ShowDIB3 establishes a palette according to the color table in DIB. If there is no color table in DIB - usually the case of 16-bit, 24-bit, and 32-bit DIB - no color panel is established. When DIB is displayed in 8-bit dollar display mode, it can only display 20 colors that are reserved. There are two solutions to this issue: the first is to simply use the "universal" palette, which is suitable for many graphics. You can also build a colorish plate yourself. The second solution is to analyze the dib of the dib, and determine the best color to display the image. Obviously, the second method will involve more work (so on the program writing, but I will tell you how to use the second method before this chapter. "Universal" color palette The showdib4 shown in the formula 16-14 establishes a universal palette, which is used to display all DIBs loaded into the program. In addition, ShowDIB4 is very similar to ShowDIB3. Cheng 16-14 showdib4showdib4.c / * ----------------------------------------- --------------------------------- Showdib4.c - Displays Dib with "all-purpose" Palette (C CHARLES PETZOLD, 1998 --------------------------------------------- ------------------------------- * / #include wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor (NULL , IDC_ARROW); wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); wndclass.lpszMenuName = szAppName; wndclass.lpszClassName = szAppName;! if (RegisterClass (& wndclass)) {MessageBox (NULL, TEXT ( "This program requires Windows NT! "), szAppName, MB_ICONERROR); return 0;} hwnd = CreateWindow (szAppName, TEXT (" Show DIB # 4: All-Purpose Palette "), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL ); ShowWindow (hwnd, icmdshow); UpdateWindow (HWND); While (GetMessage (& MSG, NULL, 0, 0)) {TranslateMessage (& MSG); DispatchMessage (& MSG);} return msg.wparam;} / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ----------------------------- CreateAllPurposepalette: CreateAllPurposepalette: Creates A Palette Suitable for a Wide Varietyof images; The Palette Has 247 Entries, But 15 of THEM area 20 Colors. -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ------------------------------------- * / HPALETTE CREATEALLPURPOSEPALETTE (Void) {HPALETTE HPALETTE; INT I, INCR, R, G, B; LOGPALETTE * PLP; plp = malloc (sizeof (LOGPALETTE) 246 * sizeof (PALETTEENTRY)); plp-> palVersion = 0x0300; plp-> palNumEntries = 247; // The following loop calculates 31 gray shades, but 3 of them // will match the Standard 20 Colors For (i = 0, g = 0, incr = 8; g <= 0xff; i , g = incr) {plp-> palpalent [i] .pered = (byte) g; plp-> palpalent [i]. PEGREEN = (byte) g; plp-> palpalentry [i] .peblue = (byte) g; plp-> palpalentry [i] .peflags = 0; INCR = (INCR == 9? 8: 9); . For (r = 0; r <= 0xff; r = 0x33) for (g = 0; g <= 0xFF; g = 0x33) for (b = 0; B <= 0xff; b = 0x33) {PLP -> palpalentry [i] .pered = (byte) r; plp-> palpalent [i] .pegreen = (byte) g; plp-> palpalent [i] .peblue = (byte) B; PLP-> Palpalent [i ] .peflags = 0; i ; hPALETTE = CREATEPALETTE (PLP); Free (plp); return hpalette;} LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {static BITMAPINFO * pPackedDib; static HPALETTE hPalette; static int cxClient, cyClient; static OPENFILENAME ofn; static TCHAR szFileName [MAX_PATH], szTitleName [MAX_PATH]; static TCHAR SZFILTER [] = text ("Bitmap Files (* .bmp) / 0*.bmp/0") Text ("All Files (*. *) / 0 *. * / 0/0"); HDC HDC; PaintStruct PS ; switch (message) {case WM_CREATE: ofn.lStructSize = sizeof (OPENFILENAME); ofn.hwndOwner = hwnd; ofn.hInstance = NULL; ofn.lpstrFilter = szFilter; ofn.lpstrCustomFilter = NULL; ofn.nMaxCustFilter = 0; ofn. nFilterIndex = 0; ofn.lpstrFile = szFileName; ofn.nMaxFile = MAX_PATH; ofn.lpstrFileTitle = szTitleName; ofn.nMaxFileTitle = MAX_PATH; ofn.lpstrInitialDir = NULL; ofn.lpstrTitle = NULL; ofn.Flags = 0; ofn.nFileOffset = 0; OFN.NFILEEXTENSION = 0; OFN.LPSTRDEFEXT = TEXT ("BMP"); OFN.LCUSTDATA = 0; off.lpfnhook = null; OFN.LPTEMPLATENAME = NULL; // Create the all-purpose Palette HPALETTE = CREATEALLPURPOSEPALETTE (); RETURN 0; Case WM_SIZE: CXClient = loword (lparam); cyclient = HiWord (LPARAM); Return 0; Case WM_Command: Switch (WPARAM) {CASE IDM_FILE_OPEN: // Show the file open dialog box if return 0 (GetOpenFileName (& ofn)!); // If there's an existing packed DIB, free the memoryif (pPackedDib) {free (pPackedDib); pPackedDib = NULL;} // Load the packed DIB into memorySetCursor (LoadCursor (NULL, IDC_WAIT); showcursor (true); PPACKEDDIB = PackedDibload (SZFileName); Showcursor (False); SetCursor (LoadCursor (NULL, IDC_ARROW); IF (! PPACKEDDIB) {MessageBox ("cannot loading dib file", szappname, 0);} invalidateect (hwnd, null, true); return 0;} Break; Case WM_Paint: hdc = beginpaint (hwnd, & ps); if (pPackedDib) {SelectPalette (hdc, hPalette, FALSE); RealizePalette (hdc); SetDIBitsToDevice (hdc, 0,0, PackedDibGetWidth (pPackedDib), PackedDibGetHeight (pPackedDib), 0,0,0, PackedDibGetHeight (pPackedDib), PackedDibGetBitsPtr ( PPACKEDDIB), PPACKEDDIB, DIB_RGB_COLORS);} Endpaint (HWND, & PS); Return 0; Case WM_QUERYNEWPALETTE: HDC = Getdc (HWND); SelectPalette (HDC, HPALETTE, FALSE); RealizePalette (HDC); InvalidateRect (HWND, NULL, TRUE); ReleaseDC (HWND, HDC); Return True; Case WM_PALETTECHANGED: IF ((hwnd) WPARAM! = HWND) HDC = getDC (hwnd); SelectPalette (HDC, HPALETTE, FALSE); RealizePalette (HDC); UpdateColors (HDC); ReleaseDC (HWND, HDC); Break; Case WM_DESTROY: IF (PPACKEDDIB); PPACKEDDIB DeleteObject (HPALETTE); PostQuitMessage (0); return 0;} return DefWindowProc (hwnd, message, wParam, lParam);} SHOWDIB4.RC (excerpt) // Microsoft Developer Studio generated resource script # include "resource.h" #include "afxres.h. "/// MenushowDib4 Menu Discardable Beginpopup" & Open "BeginMenuItem" & File ", IDM_FILE_OPENEndendResource.h (excerpt) // Microsoft Developer Studio generated include file.// buy by showdib4.rc #define IDM_FILE_OPEN 40001 When processing the WM_CREATE message, ShowDIB4 will call CREATEALLPURPOSEPALETTE and retain it in the program, and it deletes it during WM_DESTROY message processing. Because the program knows that the color panel must exist, it is not necessary to check the existence of the color tray when processed WM_PAINT, WM_QUERYNEWPALETTE or WM_PALETTECHANGETTE or WM_PALETTECHANGED message. The CreateAllPurposepalette function seems to establish a logical color panel with 247 items, which exceeds 236 items that allow programmators to allow programmatings. This is true, but this is very convenient. 15 of these projects are replicated or mapped to 20 standard retention colors. CreateAllPurposepalette starts from the establishment of 31 grayscale, namely 0x00, 0x09, 0x11, 0x1a, 0x22, 0x2b, 0x33, 0x3c, 0x44, 0x4d, 0x6f, 0x77, 0x80, 0x88, 0x91, 0x99, 0xa2, 0xAA, 0XB3, 0XBB, 0XC4, 0XCC, 0xD5, 0xDD, 0xE6, 0XEE, 0xF9 and 0xFF red, green, and blue values. Note that the first, last and intermediate projects are in the standard 20 reserved colors. The next function creates color 0x00, 0x33, 0x66, 0x99, 0xcc and 0xFF in all combinations of red, green and blue values. This has a total of 216 colors, but 8 colors have copied the standard 20 reserved colors, while the other 4 copies the grayscale. If you set the PaletteEntry structure to 0, Windows will not place the copied item into the system palette. Obviously, the actual program does not want to calculate the best color disc of the 16-bit, 24-bit or 32-bit DIB, and the program will continue to use the DIB color table to display the 8-bit di DIB. Showdib4 does not complete this work, it is only using a general palette for each matter. Because ShowDIB4 is a display program, you can compare with the 8-bit dib DIB displayed by ShowDIB3. If you look at some portraits of color DIB, you may get this conclusion: showdib4 does not have enough colors to accurately represent bright hue. If you test with the CreateAllPurposePalette function in ShowDIB4 (probably by reducing the size of the logical color panel to only a few items), you will find that Windows will only use color when the color disc is selected as the content of the device. The color in the disc is not used in the color of the 20 color palette. Mid-color tone disc The Windows API includes a universal palette, which can be obtained by calling CREATEHALFTONEPALETTE. The method of using this tuning disk is the same as the method of getting a toner using the CreateAllPurposePalette in showdib4, or you can also use the Halftone setting in the dot matrix zoom mode - use with SetStRetChbltMode. The showdib5 shown in the formula 16-15 demonstrates the method of using an intermediate color tone. Co-style 16-15 showdib5showdib5.c / * ----------------------------------------- --------------------------------- Showdib5.c - Displays Dib with Halftone Palette (C) Charles Petzold, 1998 -------------------------------------------------- ------------------------ * / #include LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); TCHAR szAppName [] = TEXT ( "ShowDib5"); int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {HWND hwnd; MSG msg; WNDCLASS wndclass ; wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor ( NULL, IDC_ARROW; WNDCLASS.HBRBACKGROUND = (Hbrush) getStockObject (white_brush); WNDCLASS.LPSZMENUNAME = szappname; WNDCLASS.LPSZCLASSNAME = Szappname; IF (! RegisterClass (& Wndclass)) {MessageBox (Null, Text ("This Program Requires Windows NT!"), SZAPPNAME, MB_ICONERROR); RETURN 0;} hwnd = CreateWindow (szAppName, TEXT ( "Show DIB # 5: Halftone Palette"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ShowWindow (hwnd, icmdshow); UpdateWindow (HWND); While (GetMessage (& MSG, NULL, 0, 0)) {TranslateMessage (& MSG); DispatchMessage (& MSG);} return msg.wparam;} LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {static BITMAPINFO * pPackedDib; static HPALETTE hPalette; static int cxClient, cyClient; static OPENFILENAME ofn; static TCHAR szFileName [MAX_PATH], szTitleName [MAX_PATH]; static TCHAR SZFILTER [] = text ("Bitmap Files (* .bmp) / 0*.bmp/0") Text ("All Files (*. *) / 0 *. * / 0/0"); HDC HDC; PaintStruct PS ; switch (message) {case WM_CREATE: ofn.lStructSize = sizeof (OPENFILENAME); ofn.hwndOwner = hwnd; ofn.hInstance = NULL; ofn.lpstrFilter = szFilter; ofn.lpstrCustomFilter = NULL; ofn.nMaxCustFilter = 0; ofn.nFilterIndex = 0; ofn.lpstrFile = szFileName; ofn.nMaxFile = MAX_PATH; ofn.lpstrFileTitle = szTitleName; ofn.nMaxFileTitle = MAX_PATH; ofn.lpstrInitialDir = NULL; ofn.lpstrTitle = NULL; ofn.Flags = 0; ofn.nFileOffset = 0 ; OFN.NFILEEXTENSION = 0; OFN.LPSTRDEFEXT = TEXT ("BMP"); OFN.LCUSTDATA = 0; OFN.LPFNHOOK = NULL; OFN.LPTEMPLATENAME = NULL; // CREATE The all-purpose Palette HDC = getdc (hwnd); HPALETTE = CREATEHALFTONEPALETTE (HDC); ReleaseDC (HWND, HDC); Return 0; Case WM_SIZE: CXClient = loword (lparam); cyclient = HiWord (LPARAM); Return 0; Case WM_Command: Switch (WPARAM) {CASE IDM_FILE_OPEN: // Show the file open dialog box IF (! getopenfilename (& off)) Return 0; // if there is an existing packed dib, free the memory IF (PPACKEDDIB) {free (PPACKEDDIB); PPACKEDDIB = NULL;} // Load The Packed Dib Into Memory SetCursor (LoadCursor (NULL, IDC_WAIT); showcursor (TRUE); PPACKEDDIB = PackedDibload (SZFileName); Showcursor (False); SetCursor (LoadCursor (NULL, IDC_ARROW); IF (! ppackedDIB) {MessageBox (HWND, Text ("Cannot Load Dib file"), Szappname, 0);} invalidateRect (hwnd, null, true); return 0;} Break; Case WM_Paint: HDC = BeginPaint (HWND, & PS); IF (PPACKEDDIB) {// set Halftone Stretch Mode SetStretchbltmode (HDC, HALFTONE); Setbrushorgex (HDC, 0, 0, NULL); // Select and realize haldtone Palette SelectPalette (HDC, HPALETTE, FALSE); REALIZEPALETTE (HDC); // StretchDIBits rather than SetDIBitsToDeviceStretchDIBits (hdc, 0,0, PackedDibGetWidth (pPackedDib), PackedDibGetHeight (pPackedDib), 0,0, PackedDibGetWidth (pPackedDib), PackedDibGetHeight (pPackedDib), PackedDibGetBitsPtr (pPackedDib), pPackedDib, DIB_RGB_COLORS, SRCCOPY);} Endpaint (hwnd, & ps); RETURN 0; Case WM_QuerynewPalette: HDC = getdc (hwnd); SelectPalette (HDC, HPALETTTE, FALSE); RealizePalette (HDC); InvalIdateRect (hwnd, null, true); ReleaseDC (HWND, HDC); Return True; Case WM_PALETTECHANGED: IF ((hwnd) WPARAM! = HWND) HDC = getDC (hwnd); SelectPalette (HDC, HPALETTE, FALSE); RealizePalette (HDC); UpdateColors (HDC); ReleaseDC (HWND, HDC); Break; Case WM_DESTROY: IF (PPACKEDDIB); PPACKEDDIB DeleteObject (HPALETTE); PostQuitMessage (0); return 0;} return DefWindowProc (hwnd, message, wParam, lParam);} SHOWDIB5.RC (excerpt) // Microsoft Developer Studio generated resource script # include "resource.h" #include "afxres.h. " ///Mushowdib5 Menu Discardable Beginpopup "& Open" BeginMenuItem "& File", IDM_FILE_OPENEndendResource.h (Explore) // Microsoft Developer Studio Generated Include File./ USED by showdib5.rc #define idm_file_open 40001ShowDIB5 program is similar to showdib4, showdib4 does not use color tables in DIB, and uses a piglet disk for larger image range. To this end, ShowDIB5 uses a logical color palette supported by Windows, and its code can be obtained from the CreatehalftonePalette letter. The intermediate color tone disc is not more complicated than the palette built by the CreateAllPurposepalette in ShowDIB4. Indeed, if it is just from being used, the result is similar. However, if you call the following two functions: SetStretchBltmode (HDC, HALFTONE); Setbrushorgex (HDC, X, Y, Null); where x and y are the device coordinates in the upper left corner of DIB, and if you use stretchdibits instead of setDibitStodeVice to display DIB, then the result will surprise you : Color tone is more accurate to use CreateAllPurposePalette or CreateHalftonePalette than do not set a dot matrix zoom mode. Windows uses a mixed color pattern to handle the color on the middle toner disc to make it closer to the color of the original image on the card. As you think, the disadvantage is to do more processing time. Index coloring plate color The FclRuse parameters of SetDibitStode, CreateDibitStode, CreateMap, SetDibits, GetDibits, and Createdibits, CreateDibitStode, CreateDibitStode, CreateStode, CreateDibits, GetDibits, and Createdibits are now started. Typically, you set this parameter to DIB_RGB_COLORS (equal to 0). However, you can set it to DIB_PAL_COLORS. In this case, it is assumed that the color table in the BitmapInfo structure does not include the RGB color value, but includes a 16-bit index of the color item in the logical color plate. The logical color tray is the one currently selected in the device content that is passed to the function as the first parameter. In fact, in the createDibSection, the reason why you need to specify a non-NULL device content code as the first parameter, just because DIB_PAL_COLORS is used. What can DIB_PAL_COLORS do? It can improve some performance. Consider the 8-bit di DIB displayed in the 8-bit chamfering mode to display SetDibitStodevice. Windows first must search in all colors of the DIB color table closest to the device. Then set a small table to map the DIB iconic value to the device. That is, you need to search for 256 closest colors. However, if the DIB color table contains a logical color palette item index that selects a color from the device content, it is possible to skip the search. In addition to using the palette index, the showdib6 shown in the program 16-16 is similar to ShowDIB3. Co-style 16-16 showdib6showdib6.c / * ----------------------------------------- --------------------------------- Showdib6.c - Display Dib with Palette Indices (C) Charles Petzold, 1998 ------------------------------------- --------------------------- * / #include LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); TCHAR szAppName [] = TEXT ( "ShowDib6"); int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {HWND hwnd; MSG msg; WNDCLASS wndclass ; wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor (NULL , IDC_ARROW); wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); wndclass.lpszMenuName = szAppName; wndclass.lpszClassName = szAppName;! if (RegisterClass (& wndclass)) {MessageBox (NULL, TEXT ( "This program requires Windows NT! "), szappname, MB_ICONERROR); RETURN 0;} hwnd = CreateWindow (szAppName, TEXT ( "Show DIB # 6: Palette Indices"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ShowWindow (hwnd, icmdshow); UpdateWindow (HWND); While (GetMessage (& MSG, NULL, 0, 0)) {TranslateMessage (& MSG); DispatchMessage (& MSG);} return msg.wparam;} LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {static BITMAPINFO * pPackedDib; static HPALETTE hPalette; static int cxClient, cyClient; static OPENFILENAME ofn; static TCHAR szFileName [MAX_PATH], szTitleName [MAX_PATH]; static TCHAR SZFILTER [] = text ("Bitmap Files (* .bmp) / 0*.bmp/0") Text ("All Files (*. *) / 0 *. * / 0/0"); HDC HDC; INT I , Inumcolors; PaintStruct PS; Word * Pwindex; switch (message) {case WM_CREATE: ofn.lStructSize = sizeof (OPENFILENAME); ofn.hwndOwner = hwnd; ofn.hInstance = NULL; ofn.lpstrFilter = szFilter; ofn.lpstrCustomFilter = NULL; ofn.nMaxCustFilter = 0; ofn.nFilterIndex = 0; ofn.lpstrFile = szFileName; ofn.nMaxFile = MAX_PATH; ofn.lpstrFileTitle = szTitleName; ofn.nMaxFileTitle = MAX_PATH; ofn.lpstrInitialDir = NULL; ofn.lpstrTitle = NULL; ofn.Flags = 0; ofn.nFileOffset = 0 ; off.nfileextension = 0; OFN.LPSTRDEFEXT = text ("bmp"); OFN.LCUSTDATA = 0; OFN.LPFNHOOK = NULL; OFN.LPTEMPLATENAME = NULL; RETURN 0; Case WM_SIZE: CXClient = loword (lparam); cyclient = HiWord (LPARAM); Return 0; Case WM_Command: Switch (WPARAM) {CASE IDM_FILE_OPEN: // Show the file open dialog boxif (! Getopenfilename (& off)) Return 0; // if there's an existing pack Dib, Free the memory IF (PPACKEDDIB) {free (PPACKEDDIB); PPACKEDDIB = NULL;} // if there's an existing logical palette, delete it IF (HPALETTE) {deleteObject (HPALETTE); HPALETTE = null;} // Load the Packed Dib Into Memory SetCursor (LoadCursor (NULL, IDC_WAIT); showcursor (TRUE); PPACKEDDIB = PackedDibload (SZFileName); Showcursor (False); SetCursor (LoadCursor (NULL, IDC_ARROW); IF (PPACKEDDIB) {// Create The Palette from the Dib Color Table HPALETTE = PACKEDDIBCREATEPALETTE (PPACKEDDIB); // Replace Dib Color Table with INDES IF (HPALETTE) {Inumcolors = PackedDibGetNumColors (PPACKEDDIB); PWINDEX = (Word *) PackedDibgetColortablePtr (PPACKEDDIB); For (i = 0; i if (hPalette) {SelectPalette (hdc, hPalette, FALSE); RealizePalette (hdc);} if (pPackedDib) SetDIBitsToDevice (hdc, 0,0, PackedDibGetWidth (pPackedDib), PackedDibGetHeight (pPackedDib), 0,0,0, PackedDibGetHeight ( PpackedDib), PackedDibgetBitsptr (PpckedDib), PPACKEDDIB, DIB_PAL_COLORS; Endpaint (HWND, & PS); Return 0; Case WM_QUERYNEWPALETTE: IF (! hpalette) Return False; HDC = Getdc (HWND); SelectPalette (HDC, HPALETTE, FALSE); RealizePalette (HDC); InvalidateERECT (HWND, NULL, TRUE); ReleaseDC (HWND, HDC); Return True; Case WM_PALETTECHANGED: IF (! hpalette || (hwnd) wparam == hwnd) Break; HDC = getDC (hwnd); SelectPalette (HDC, HPALETTE, FALSE); RealizePalette (HDC); UpdateColors (HDC); ReleaseDC (HWND, HDC); Break; Case WM_DESTROY: IF (PPACKEDDIB) FREE (PPACKEDDIB); IF (HPALETTE) deleteObject (HPALETTE); PostQuitMessage (0); return 0;} return DefWindowProc (hwnd, message, wParam, lParam);} SHOWDIB6.RC (excerpt) // Microsoft Developer Studio generated resource script # include "resource.h" #include "afxres.h. " /// MenuSHOWDIB6 MENU DISCARDABLE BEGINPOPUP "& File" BEGINMENUITEM "& Open", IDM_FILE_OPENENDENDRESOURCE.H (excerpt) // Microsoft Developer Studio generated include file.// Used by ShowDib6.rc // # define IDM_FILE_OPEN 40001SHOWDIB6 DIB will be loaded into memory After this, the color disc is created, and the showdib6 simply replaces the color in the DIB color table with the Word index started. The PackedDibgetNumColors correspondence will indicate how many colors, while the PackedDibgetColortablePtr function is transmitted to the indicator of the start position of the DIB color table. Note that this technology is only possible when only a coloring disk is created directly from the DIB color table. If you use a universal palette, you must search the closest color to get the index of the DIB. If you want to use a palette index, you do replace the color table in DIB before you store DIB to the magnetic sheet. Also, don't put DIB containing the palette index into the scrapbook. In fact, before displaying, put the tuning disk index into the DIB, then put the RGB color value back, it will be safer. Pamper and dot matrix object SHOWDIB7 program in the process 16-17 shows how to use a piggy bank associated with DIB, which is converted into a GDI dot matrix object using the CreatedIBitMap function. Cheng 16-17 showdib7showdib7.c / * ----------------------------------------- --------------------------------- Showdib7.c - shows dib conveilted to ddb (c) Charles Petzold, 1998 -------------------------------------------------- -------------------------- / #include LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); TCHAR szAppName [] = TEXT ( "ShowDib7"); int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {HWND hwnd; MSG msg; WNDCLASS wndclass ; wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor (NULL , IDC_ARROW); WNDCLASS.HBRBACKGROUND = (Hbrush) getStockObject (white_brush); WNDCLASS.LPSZMENUNAME = SZAPPNAME; WNDCLASS.LPSZCLASSNAME = szAppname; IF (! RegisterClass (& Wndclass)) {MessageBox (Null, Text ("This Program Requires Windows NT!"), SZAPPNAME, MB_ICONERROR); RETURN 0;} hwnd = CreateWindow (szAppName, TEXT ( "Show DIB # 7: Converted to DDB"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ShowWindow (HWnd, Icmdshow); UpdateWindow (HWND); While (GetMessage (& MSG, NULL, 0, 0)) {TranslateMessage (& MSG); DispatchMessage (& MSG);} return msg.wparam;} LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {static HBITMAP hBitmap; static HPALETTE hPalette; static int cxClient, cyClient; static OPENFILENAME ofn; static TCHAR szFileName [MAX_PATH], szTitleName [MAX_PATH]; static TCHAR szFilter [] = Text ("Bitmap Files (* .bmp) / 0*.bmp/0") Text ("All Files (*. *) / 0 *. * / 0/0"); Bitmap Bitmap; BitmapInfo * PPACKEDDIB HDC HDC, HDCMEM; PaintStruct PS; switch (message) {case WM_CREATE: ofn.lStructSize = sizeof (OPENFILENAME); ofn.hwndOwner = hwnd; ofn.hInstance = NULL; ofn.lpstrFilter = szFilter; ofn.lpstrCustomFilter = NULL; ofn.nMaxCustFilter = 0; ofn.nFilterIndex = 0; ofn.lpstrFile = szFileName; ofn.nMaxFile = MAX_PATH; ofn.lpstrFileTitle = szTitleName; ofn.nMaxFileTitle = MAX_PATH; ofn.lpstrInitialDir = NULL; ofn.lpstrTitle = NULL; ofn.Flags = 0; ofn.nFileOffset = 0 ; OFN.NFILEEXTENSION = 0; OFN.LPSTRDEFEXT = TEXT ("BMP"); OFN.LCUSTDATA = 0; OFN.LPFNHOOK = NULL; OFN.LPTEMPLATENAME = NULL; Return 0; Case WM_SIZE: CXClient = loword (lparam); cyclient = HiWord (LPARAM); Return 0; Case WM_Command: Switch (WPARAM) {CASE IDM_FILE_OPEN: // Show the file open dialog box IF (! getopenfilename (& off)) Return 0; // if there is an existing packed dib, free the memory IF (hbitmap) {deleteObject (hbitmap); hbitmap = null;} // if there is an existing logical palette, delete it IF (HPALETTE) {deleteObject (HPALETTE); HPALETTE = NULL;} // Load The Packed Dib Into MemorySetCursor (LoadCursor (NULL, IDC_WAIT); showcursor (TRUE); PPACKEDDIB = PackedDibload (SZFileName); Showcursor (False); SetCursor (LoadCursor (NULL, IDC_ARROW); IF (PPACKEDDIB) {// Create Palette from The Dib and SELECT IT INTO DC HPALETTE = PACKEDDIBCREATEPALETTE (PPACKEDDIB); hdc = GetDC (hwnd); if (hPalette) {SelectPalette (hdc, hPalette, FALSE); RealizePalette (hdc);} // Create the DDB from the DIBhBitmap = CreateDIBitmap (hdc, (PBITMAPINFOHEADER) pPackedDib, CBM_INIT, PackedDibGetBitsPtr (pPackedDib ), ppackeddib, dib_rgb_colors; releasedc (hwnd, hdc); // free the packed-dib memory Free (PPACKEDDIB);} else {MessageBox (HWND, Text ("Cannot Load Dib file"), Szappname, 0);} InvalidateRect (HWND, NULL, TRUE); Return 0;} Break; Case WM_Paint: HDC = BeginPaint HWND, & PS); IF (HPALETTE) {SELECTPALETTTE (HDC, HPALETTE, FALSE) ;RIZEPALETTE (HDC);} if (hbitmap) {getObject (HbitMap, Sizeof (Bitmap), & Bitmap HDCMEM = CREATECOMPATIPLEDC (HDC); SELECTOBJECT (HDCMEM, HBitmap); Bitblt (HDC, 0, 0, Bitmap.Bmwidth, Bitmap.Bmheight, HDCMEM, 0, 0, SRCCOPY); DELETEDC (HDCMEM); Endpaint (HWND, & PS); RETURN 0; Case WM_QUERYNEWPALETTE: IF (! hpalette) Return False; HDC = Getdc (HWND); SelectPalette (HDC, HPALETTE, FALSE); RealizePalette (HDC); InvalidateERECT (HWND, NULL, TRUE); ReleaseDC (HWND, HDC); Return True; Case WM_PALETTECHANGED: IF (! hpalette || (hwnd) wparam == hwnd) Break; HDC = getDC (hwnd); SelectPalette (HDC, HPALETTE, FALSE); RealizePalette (HDC); UpdateColors (HDC); ReleaseDC (HWND, HDC); Break; Case WM_DESTROY: IF (HbitMap) deleteObject (HbitMap); IF (HPALETTE) deleteObject (HPALETTE); PostQuitMessage (0); return 0;} return DefWindowProc (hwnd, message, wParam, lParam);} SHOWDIB7.RC (excerpt) // Microsoft Developer Studio generated resource script # include "resource.h" #include "afxres.h. " /////Ushnowdib7 menu discardable beginpopup "& file" BeginMenuItem "& Open", IDM_FILE_OPENEndendResource.h (excerpt) // Microsoft Developer Studio generated include file.// buy by showdib7.rc #define idm_file_open 40001 Like the previous program, ShowDIB7 has a metrics pointing to Packed Dib, the "File" command of the DIB responding to the menu, "Open" command. The program has established a palette from the PACKED DIB, and is still during the processing of the WM_COMMAND message - obtain the contents of the device displayed for video display, and select the color panel, display the palette. The showdib7 then calls CREATEDIBITMAP to establish DDB from DIB. If the toner does not select the device content and appear, the DDB established by CreateDibitMap will not use the additional colors in the logical tuning disc. After calling createDibitmap, the program will release the memory space occupied by the Packed DIB. PPACKEDDIB variables are not static variables. Conversely, ShowDIB7 retains the dot matrix code (HbitMap) and the logical color palette (HPALETTE) by static variable. During the WM_PAINT message processing, the toner is again selecting the contents of the device and appears. The GetObject function can get the width and height of the point line. Then, the program is displayed by establishing a compatible memory device content in the display area, selecting a dot matrix, and performs Bitblt. The palette used when the DDB is displayed, must be the same as it is created from the CREATEDIBITMAP call. If you copy a dot matrix to a scrapbook, it is best to use the Packed DIB format. Then Windows can provide the dot matrix object to the program that wants to use these dot matrix. However, if you need to copy the dot matrix object to the scrapbook, first get the content of the video device and display the palette. This allows Windows to convert DDB to DIB based on the current system color tray. Palette and DIB block Finally, ShowDIB8 shown in the formula 16-18 illustrates how to use a palette with a DIB block. Cheng Ti16-18 showdib8showdib8.c / * ----------------------------------------- --------------------------------- Showdib8.c - shows dib conveilt to dib section (c) Charles Petzold, 1998 ------------------------------------- -------------------------- / #include LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); TCHAR szAppName [] = TEXT ( "ShowDib8"); int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {HWND hwnd; MSG msg; WNDCLASS wndclass ; wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor ( NULL, IDC_ARROW; WNDCLASS.HBRBACKGROUND = (Hbrush) getStockObject (white_brush); WNDCLASS.LPSZMENUNAME = szappname; WNDCLASS.LPSZCLASSNAME = Szappname; IF (! RegisterClass (& Wndclass)) {MessageBox (Null, Text ("This Program Requires Windows NT!"), SZAPPNAME, MB_ICONERROR); RETURN 0;} hwnd = CreateWindow (szAppName, TEXT ( "Show DIB # 8: DIB Section"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ShowWindow (hwnd, icmdshow); UpdateWindow (HWND); While (GetMessage (& MSG, NULL, 0, 0)) {TranslateMessage (& MSG); DispatchMessage (& MSG);} return msg.wparam;} LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {static HBITMAP hBitmap; static HPALETTE hPalette; static int cxClient, cyClient; static OPENFILENAME ofn; static PBYTE pBits; static TCHAR szFileName [MAX_PATH], szTitleName [MAX_PATH] static tchar szfilter [] = text ("Bitmap files (* .bmp) /0*.bmp/0") Text ("all files (*. *) / 0 *. * / 0/0"); Bitmap Bitmap BitmapInfo * PPACKEDDIB; HDC HDC, HDCMEM; PAINTSTRUCT PS; switch (message) {case WM_CREATE: ofn.lStructSize = sizeof (OPENFILENAME); ofn.hwndOwner = hwnd; ofn.hInstance = NULL; ofn.lpstrFilter = szFilter; ofn.lpstrCustomFilter = NULL; ofn.nMaxCustFilter = 0; ofn.nFilterIndex = 0; ofn.lpstrFile = szFileName; ofn.nMaxFile = MAX_PATH; ofn.lpstrFileTitle = szTitleName; ofn.nMaxFileTitle = MAX_PATH; ofn.lpstrInitialDir = NULL; ofn.lpstrTitle = NULL; ofn.Flags = 0; ofn.nFileOffset = 0 ; off.nfileextension = 0; OFN.LPSTRDEFEXT = text ("bmp"); OFN.LCUSTDATA = 0; OFN.LPFNHOOK = NULL; OFN.LPTEMPLATENAME = NULL; RETURN 0; Case WM_SIZE: CXClient = loword (lparam); cyclient = HiWord (LPARAM); Return 0; Case WM_Command: Switch (WPARAM) {CASE IDM_FILE_OPEN: // Show the file open dialog box IF (! getopenfilename (& off)) Return 0; // if there is an existing packed dib, free the memory IF (hbitmap) {deleteObject (hbitmap); hbitmap = null;} // if there is an existing logical palette, delete it IF (HPALETTE) {deleteObject (HPALETTE); HPALETTE = null;} // Load the Packed Dib Into Memory SetCursor (LoadCursor (NULL, IDC_WAIT); showcursor (TRUE); PPACKEDDIB = PackedDibload (SZFileName); Showcursor (False); SetCursor (LoadCursor (NULL, IDC_ARROW); IF (PPACKEDDIB) {// create the dib section from the dib Hbitmap = createDibsection (NULL, PPACKEDDIB, DIB_RGB_COLORS, & PBITS, NULL, 0); // Copy the bits CopyMemory (PBITS, PackedDibgetBitsptr (PPACKEDDIB), PackedDibgetBitsize (PPACKEDDIB); // Create Palette from the DIB HPALETTE = PACKEDDIBCREATEPALETTE (PPACKEDDIB); // free the packed-dib memory Free (PPACKEDDIB);} else {MessageBox (HWND, Text ("Cannot Load Dib file"), Szappname, 0);} InvalidateRect (HWND, NULL, TRUE); Return 0;} Break; Case WM_Paint: HDC = BeginPaint HWnd, & PS); IF (HPALETTE) {SelectPalette (HDC, HPALETTE, FALSE) ;RIZEPALETTE (HDC);} if (hbitmap) {GetObject (Hbitmap, Sizeof (Bitmap), & Bitmap HDCMEM = CREATECOMPATIPLEDC (HDC); SELECTOBJECT (HDCMEM, HBitmap); Bitblt (HDC, 0, 0, Bitmap.bmwidth, Bitmap.Bmheight, HDCMEM, 0, 0, SRCCopy); DELETEDC (HDCMEM); Endpaint (HWND, & PS); RETURN 0; Case WM_QUERYNEWPALETTE: IF (! hpalette) Return False; HDC = Getdc (HWND); SelectPalette (HDC, HPALETTE, FALSE); RealizePalette (HDC); InvalidateERECT (HWND, NULL, TRUE); ReleaseDC (HWND, HDC); Return True; Case WM_PALETTECHANGED: IF (! hpalette || (hwnd) wparam == hwnd) Break; HDC = getDC (hwnd); SelectPalette (HDC, HPALETTE, FALSE); RealizePalette (HDC); UpdateColors (HDC); ReleaseDC (HWND, HDC); Break; Case WM_DESTROY: IF (HbitMap) deleteObject (HbitMap); IF (HPALETTE) deleteObject (HPALETTE); PostQuitMessage (0); return 0;} return DefWindowProc (hwnd, message, wParam, lParam);} SHOWDIB8.RC (excerpt) // Microsoft Developer Studio generated resource script # include "resource.h" #include "afxres.h. " ///////////// ' #define idm_file_open 40001 WM_PAINT processing in ShowDib7 and showdib8 is the same: two programs use a dot matrix code code (hbitmap) and a logical color panel (HPALETTE) as static variables. The palette is selected into the device content and appears, the width and height of the dot matrix are obtained from the GetObject function, and the program is established and the point-in-line map is selected, and then the dot matrix is displayed to the display area. The biggest difference between the two programs is to process the program of "File", "Open" function table command. After obtaining the indicators to the PACKED DIB and established a toner, showdib7 must select the color panel to the video device content and appear before calling createDibitmap. Showdib8 calls CREATEDIBSECTION after obtaining the Packed Dib metrics. It is not necessary to select the palette to the device content because CREATEDIBSECTION does not convert DIB to device-related formats. Indeed, the unique use of the first parameter of CreatedibSection (ie, the device content code) is whether you use the Dib_Pal_Colors flag. After calling createDibsection, showdib8 copies the icon dollar from the PACKED DIB to the memory location returned from the CREATEDIBSECTION card, and then calls PackedDibcreatePalette. Although this function is easy to use, showdib8 will establish a color panel based on information returned from getDibcolortable. DIB processing program library It is now - after we learn from the GDI dot matrix object, the device is independent of the point line, the DIB block and the Windows Toner Manager - we have done a letter that helps to handle the point of view. Preparation of the formula. The previous PACKEDIB file shows a possible method: the PACKED DIB in the memory is represented by the indicator pointing to it. All information about DIBs can be obtained from a function of the access header information structure. However, this method will generate serious execution issues when "Get Pixel" and "SET PIXEL" are currently. Image processing tasks must of course access dot matrix elements, and these functions should also be as fast as possible. Possible C solutions include establishing a DIB category, at which point the indicator pointing to the Packed Dib is just a member variable. Other member variables and membership functions help to perform a commonality in the DIB faster. However, because I have pointed out in Chapter 1, you only need to understand C, using C will be the scope of other books. Of course, you can do it with C . A good example is that many Windows functions use the code. In addition to the code as a value as a value, what is the application understand what it? Program knows that the code references special libraries, and also knows that the function is used to process existing objects. Obviously, the operation system uses a code to reference the internal information of the object. The code can be as simple as the structural index. For example, assume that there is a set of functions, which use a code called HDIB. What is HDIB? It may be defined in a header file as follows: Typedef void * hdib; This definition has answered "HDIB what" with "Nothing". However, in fact, HDIB may be structural indicators, which includes not only indicators to Packed Dib, but also other information: TypeDef struct {bitmapinfo * ppackedDib; int CX, CY, CBITSPERPIXEL, CBYTESPERROW; BYTE * PBITS; {Dibstructure, * PDIBStructure; This structure has other five fields that are taken from Packed Dib. Of course, these values are allowed to access them more quickly. Different DIB program libraries can handle this structure instead of PPACKEDDIB metrics. The method can be performed in the following DibGetPixelPointer function: BYTE * DibGetPixelPointer (HDIB hdib, int x, int y) {PDIBSTRUCTURE pdib = hdib; return pdib-> pBits y * pdib-> cBytesPerRow x * pdib-> cBitsPerPixel / 8;} Of course, this method may be faster than the "Get Pixel" in Packedib.c. Since this method is very reasonable, I decided to give up PACKED DIB and switch to the DIB program library that handles DIB blocks. This actually makes us more elasticity for the processing of Packed Dib (that is, manipulating a DIB icon in a manner in which the device is independent of the device), and will be more effective when executed under Windows NT. Dibstruct structure Dibhelp.c files - so named is because of the help of processing DIB - there are thousands of lines and display in a few small sections. But first let's take a look at the structure processed by Dibhelp, which is defined in dibhelp.c as follows: typedef struct {PBYTE * ppRow; // array of row pointersint iSignature; // = "Dib" HBITMAP hBitmap; // handle returned from CreateDIBSectionBYTE * pBits; // pointer to bitmap bitsDIBSECTION ds; // DIBSECTION structureint iRShift [3]; // Right-Shift Values for Color Masksint Ilshift [3]; // Left-Shift VALUES for Color Masks} Dibstruct, * PDIBStruct; Now skip the first field. It is the first field because it makes some huge gathering. It is easier to understand the first field after discussing other fields. In dibhelp.c, when this structure is set, the second field is set to the two-entered value of the text string "DIB". Through some Dibhelp functions, the second field will be used for a tag of the structural valid indicator. The third field, that is, hbitmap, is a dot matrix code from the createDibsection letter. You will think of this code can have a variety of ways, which is the same as the code usage of the GDI dot matrix object encountered in Chapter 14. However, the code that is returned from the createDibSecion will involve a dot matrix map stored in accordance with the device, which is stored in the output device to the output device by call Bitblt and StretchBLT. The fourth field of Dibstruct is an indicator of pointing a dot matrix. This value can also be set by the createDibsection. You will remember that the operating system will control this memory block, but the application has the permissions to access it. When deleting a dot mapping code, the memory block will be automatically released. The fifth field of Dibstruct is a DibSECTION structure. If you have a dot matrix code that is transferred from the createDibsection, you can pass the code to the getobject function to get a dot matrix map for the DibSECTION structure: getObject (HbitMap, Sizeof (Dibsection), & DS); as a prompt, The DIBSECTION structure is defined in Wingdi.h as follows: typedef struct tagDIBSECTION {BITMAP dsBm; BITMAPINFOHEADER dsBmih; DWORD dsBitfields [3]; // Color masksHANDLE dshSection; DWORD dsOffset;} DIBSECTION, * PDIBSECTION; first field is the BITMAP structure, it establishes with CreateBitmapIndirect bitmap object, Remove information about DDB with GetObject. The second field is the BitmapInfoHeader structure. Regardless of whether the dot matrix information structure is passed to the createDibsection, the DIBSECTION structure has a BitMapInfoHeader structure rather than other structures, such as the BitmapCoreheader structure. This means that when this structure is accessing this structure, many of the functions in dibhelp.c do not have to check the DIB compatible with OS / 2. For the 16-bit and 32-bit dib, if the BiCompression field of the BitmapInfoHeader structure is bi_bitfields, there are usually three masks after the information header structure. These mask values determine how to convert 16-bit and 32-bit primitives to RGB colors. Mask is stored in the third field of the DibSecion structure. The last two fields of the DIBSECTION structure refers to the DIB block, which is created by the archive mapping. Dibhelp does not use this feature of CreatedibSection, so you can ignore these fields. The last two fields of Dibstruct store left and right shift values, which are used to handle the color mask of 16-bit and 32-bit DIBs. We will discuss these shift values in Chapter 15. Let's come back to see the first field of Dibstruct. As we see, when starting to establish DIB, this field is set to point to an indicator of an indicator array, and each indicator in the array points to a line of rows in DIB. These indicators allow for a DIB icon in a faster way, and are also defined so that the top row can first reference the DIB icon. The last element of this array - references the bottom of the DIB image - typically equal to the PBITS field of Dibstruct. Information Dibhelp.c To define the start of the Dibstruct structure, then provide a library set, which allows the application to obtain information about the DIB block. Cheng Ti 16-19 shows the first part of dibhelp.c. The first part of the program 16-19 Dibhelp.c file Dibhelp.c (Part 1) / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ ------------------------------------------ Dibhelp.c - DIB Section helper routines (c) Charles Petzold, 1998 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ------------------------------------ * / #include #define HDIB_SIGNATURE (* (int *) "Dib") typedef struct {PBYTE * ppRow;! // must be first field for macros int iSignature; HBITMAP hBitmap; BYTE * pBits; DIBSECTION ds; int iRShift [3]; int iLShift [3];} Dibstruct, * pdibstruct; / * -------------------------------------- -------------------------------------- Dibisvalid: returns true if HDIB Points to a Valid Dibstruct- -------------------------------------------------- -------------------------- / BOOL DibIsValid (HDIB hdib) {PDIBSTRUCT pdib = hdib; if (pdib == NULL) return FALSE; if (IsBadReadPtr (pdib, sizeof (DIBSTRUCT))) return FALSE; if (! Pdib-> iSignature = HDIB_SIGNATURE) return FALSE; Return True;} / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- DibbitmapHandle: Returns the Handle to the Dib Section Bitmap Object ----------- -------------------------------------------------- ---------------- * / Hbitmap dibbitmaphandle (HDIB HDIB) {if (! Dibisvalid (HDIB)) Return Null; Return (PDIBSTRUCT) HDIB -> hbitmap;} / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------- Dibwidth: returns the bitmap pixel width ---------------- -------------------------------------------------- ----------- * / INT Dibwidth (HDIB HDIB) {if (! Dibisvalid (HDIB)) Return 0; Return (PDIBSTRUCT) HDIB) -> DS.DSBM.BMWIDTH;} / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------- DibHeight: returns the bitmap pixel height ---------------- -------------------------------------------------- ---------- * / INT Dibheight (HDIB HDIB) {if (! Dibisvalid (HDIB)) Return 0; Return (PDIBSTRUCT) HDIB) -> DS.DSBM.BMHEIGHT;} / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------- Dibbitcount: Returns the Number of Bits Per Pixel -------------- -------------------------------------------------- ---------- * / INT Dibbitcount (HDIB HDIB) {if (! Dibisvalid (HDIB)) Return 0; Return (PDIBSTRUCT) HDIB -> DS.DSBM.BMBIXEL;} / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- DibrowLength: Returns the number of bytes per row of pixels ----------- -------------------------------------------------- ---------------- * / INT DibroWLENGTH (HDIB HDIB) {IF (! Dibisvalid (HDIB)) Return 0; Return 4 * (Dibwidth (HDIB) * Dibbitcount (HDIB) 31) / 32);} / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------- Dibnumcolors: Returns The Number of Colors in The Color Table -------------------------------- -------------------------------------------------- -------------- * / INT Dibnumcolors (HDIB HDIB) {PDIBSTRUCT PDIB = HDIB; IF (! Dibisvalid (HDIB)) Return 0; IF (PDIB-> DS.DSBMIH.BICLRUSED! = 0) {Return PDIB-> DS.DSBMIH.BICLRUSED;} else IF (Dibbitcount (HDIB) <= 8) {Return 1 << Dibbit (HDIB);} return 0 } / * ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ----------------------------- Dibmask: Returns One of the color masks ------------- -------------------------------------------------- ------------ * / DWORD Dibmask (HDIB HDIB, INT I) {PDIBSTRUCT PDIB = HDIB; IF (! Dibisvalid (HDIB) || i <0 || i> 2) Return 0; Return PDIB-> DS.DSBITFIELDS [I];} / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- Dibrshift: returns one of the right-shift values ------------ -------------------------------------------------- --------------- * / INT Dibrshift (HDIB HDIB, INT I) {PDIBSTRUCT PDIB = HDIB; if (! Dibisvalid (HDIB) || i <0 || i> 2) Return 0; Return PDIB-> Irshift [i];} / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- Diblshift: returns one of the left-shift value ------------ -------------------------------------------------- -------------- * / INT Diblshift (HDIB HDIB, INT I) {PDIBSTRUCT PDIB = HDIB; IF (! Dibisvalid (HDIB) || i <0 || i> 2) Return 0; Return PDIB-> ilshift [i];} / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------- Dibcompression: Returns the value of the bicompression field -------------- -------------------------------------------------- ---------- * / int Dibcompression (HDIB HDIB) {if (! Dibisvalid (HDIB)) Return 0; Return (PDIBSTRUCT) HDIB -> DS.DSBMIH.BICOMPIRESSION;} / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------- Dibisaddressable: Returns True IF the dib is not compressed ------------- -------------------------------------------------- ------------- * / Bool Dibisaddressable (HDIB HDIB) {Int iCompression; IF (! Dibisvalid (HDIB)) Return False; iCompression = Dibcompression (HDIB); IF (iCompression == Bi_RGB || iCompression == Bi_bitfields) Return True; Return false;} / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------- The Sse Functions Return The Sizes of Various Components of the Dib Sectionas They Would Appear In a Packed Dib. These Functions AID In ConvertingThe Dib Section To a Packed Dib and in Saving Dib Files. ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- ----------------------------------------- * / DWORD DibInfoHeaderSize (HDIB hdib) {if return 0; return ((PDIBSTRUCT) hdib) -> ds.dsBmih.biSize; (DibIsValid (hdib)!)} DWORD DibMaskSize (HDIB hdib) {PDIBSTRUCT pdib = hdib; if (DibIsValid! (HDIB)) RETURN 0; IF (PDIB-> DS.DSBMIH.BICOMPIELD == Bi_bitfields) Return 3 * SizeOf (DWORD); Return 0;} DWORD DIBCOLORSIZE (HDIB HDIB) {Return Dibnumcolors (HDIB) * Sizeof (RGBQUAD); DWORD DibinFoSize (HDIB HDIB) {Return DibinfoHeadersize (HDIB) Dibmasksize (HDIB) Dibcolorsize (HDIB); DWORD Dibbitssize (HDIB HDIB) {PDIBSTRUCT PDIB = HDIB; IF (! Dibisvalid (HDIB)) Return 0; IF (PDIB-> DS.DSBMIH.BisizeImage! = 0) {Return PDIB-> DS.DSBMIH.BisizeImage;} Return Dibheight (HDIB) * DibrowLength (HDIB); DWORD Dibtotalsize (HDIB HDIB) {Return DibinFoSize (HDIB) DibbitsSize (HDIB); / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------- THESE FUNCTIONS RETURN POINTERS TO The VARIOS Components of the Dib Section. ------------ -------------------------------------------------- ----------------- * / BitmapInfoHeader * DibinfoHeaderptr (HDIB HDIB) {if (! Dibisvalid (HDIB)) Return Null; Return & ((PDIBSTRUCT) HDIB -> DS .dsbmih); DWORD * DIBMASKPTR (HDIB HDIB) {PDIBSTRUCT PDIB = HDIB; if (! Dibisvalid (HDIB)) Return 0; Return PDIB-> DS.DSBITFIELDS;} Void * dibbitsptr (HDIB HDIB) {if (! Dibisvalid (HDIB)) Return Null; Return (PDIBSTRUCT) HDIB -> Pbits; / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------- DibsetColor: Obtains entry from the dib color table -------------- -------------------------------------------------- ------------- * / Bool DibgetColor (HDIB HDIB, INDEX, RGBQUAD * PRGB) {PDIBSTRUCT PDIB = HDIB; HDC HDCMEM; IRTURN if return 0 (DibIsValid (hdib)!); hdcMem = CreateCompatibleDC (NULL); SelectObject (hdcMem, pdib-> hBitmap); iReturn = GetDIBColorTable (hdcMem, index, 1, prgb); DeleteDC (hdcMem); return iReturn TRUE? : False;} / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- DibgetColor: Sets an entry in the dib color table ------------ -------------------------------------------------- ------------- * / Bool DibsetColor (HDIB HDIB, INDEX, RGBQUAD * PRGB) {PDIBSTRUCT PDIB = HDIB; HDC HDCMem; IRTURN IF (! Dibisvalid (HDIB)) Return 0; hdcmem = creteCompatibleDC (null); selectObject (HDCMEM, PDIB-> HbitMap); IReturn = setDibcolortable (HDCMEM, INDEX, 1, PRGB); deletedc (HDCMEM); RETURN IRETURN® TRUE: FALSE;} Most of the functions in dibhelp.c are not explained. Dibisvalid functions help protect the entire system. Other functions call Dibisvalid before trying to quote information in Dibstruct. All these functions have (and usually only) the first parameter of the HDIB type, (we will see it immediately) This parameter is defined as an empty indicator in dibhelp.h. These functions can store this parameter to PDIBSTRUCT and then reepline the fields in the structure. Pay attention to the dibisaddressable file that is back to the BOOL value. DibisnotCompRESSED functions can also be called this one. The return value represents a separate DIB iconic device. The Versuck Settings starting with DibinfoHeadersize will get different components in the PACKED DIB in the DIB block. As we see, these functions help convert DIB blocks into packed dib and store DIB files. These functions are later obtained by gaining a group of indicators to different DIB components. Although dibhelp.c includes a function named DibinfoHeaderPtr, and the function will get an indicator to the BitMapInfoHeader structure, but there is still no function to get the BitmapInfo structural indicator - that is, the information structure behind the DIB color table. This is because the application does not directly access the structure of this type when the DIB block is processed. BitmapInfoHeader structure and color masks are valid in the DibSecion structure, and spread from the CreatedibSECTION card back to the indicator of the icon dollar. At this time, you can only access the Dib Color table indirectly by calling getDibcolortable and setDibcolortable. These features are encapsulated in Dibhelp's DibgetColor and DibsetColor functions. Behind dibhelp.c, file DibcopyToInfo configures an indicator to the BitMapInfo structure, and fill information, but it is not exactly the same as the index of the existing structure in the memory. Read, write The advantage of a leading point of the Packed DIB or DIB block is to be able to manipulate the DIB icon. The second part of the DIBHELP.C shown in the formula 16-20 lists the functions that provide this feature. The second part of the program 16-20 Dibhelp.c file Dibhelp.c (second part) / * ---------------------------- ---------------------------------------------- Dibpixelptr: Returns a Pointer to the Pixel At Position (X, Y) ------------------------------------- --------------------------------------- * / Byte * dibpixelptr (HDIB HDIB, INT X, INT Y) {if (! Dibisaddressable (HDIB)) Return Null; IF (x <0 || x> = dibwidth (HDIB) || Y <0 || y> = dibheight (HDIB) RETURN NULL; RETURN ((PDIBSTRUCT) HDIB) -> PPROW) [Y] (x * Dibbitcount (HDIB) >> 3); / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------- DibgetPixel: Obtains a Pixel Value At (x, y) ----------- -------------------------------------------------- ---------------- * / DWORD DibgetPixel (HDIB HDIB, INT X, INT Y) {Pbyte Ppixel; IF (! (Ppixel = dibpixlptr (HDIB, X, Y))) Return 0; Switch (Dibbitcount (HDIB) {Case 1: Return 0x01 & ( * Ppixel >> (7 - (x & 7)))); case 4: return 0x0f & (* ppixel >> (x & 1? 0: 4)); case 8: return * ppixel; case 16: return * ( Word *) ppixel; case 24: return 0x00fffffff & * (dword *) Ppixel; case 32: return * (dword *) ppixel;} return 0;} / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ------------------------- DibsetPixel: Sets a Pixel Value At (x, y) ------------- -------------------------------------------------- ------------ * / Bool Dibsetpixel (HDIB HDIB, INT X, INT Y, DWORD dwpixel) {pbyte ppixel; if (! (Ppixel = dibpixelptr (hdib, x, y))) Return False; Switch (Dibbitcount (HDIB) {Case 1: * Ppixel & = ~ (1 << (x & 7))))); * Ppixel | = dwpixel << (7 - (x & 7)); Break; Case 4: * Ppixel & = 0x0f << (x & 1? 4: 0); * ppixel | = dwpixel << (x & 1? 0: 4); break; case 8: * ppixel = (byte) dwpixel; break; case 16: * (word *) ppixel = (Word) dwpixel; break; Case 24: * (RGBTRIPLE *) PPIXEL = * (RGBTRIPLE *) & dwpixel; Break; Case 32: * (DWORD *) PPixel = dwpixel; break; default: returnaf false;} return true; / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------- DibgetPixelcolor: Obtains the Pixel Color At (x, y) ----------- -------------------------------------------------- --------------- * / Bool Dibgetpixelcolor (HDIB HDIB, INT X, INT Y, RGBQUAD * PrGB) {DWORD DWPIXEL; INT IBITCOUNT; PDIBSTRUCT PDIB = HDIB // Get Bit Count; Also Use this as a validity check IF (0 == (ibitcount = dibbit (HDIB))) Return False; // Get the Pixel ValuedWpixel = DibgetPixel (HDIB, X, Y); // IF The Bit-Count Is 8 Or Less, Index The Color Tableif ibitcount <= 8) Return DibgetColor (HDIB, (int) dwpixel, prg); // if the bit-count is 24, Just Use the pixelse if (ibitcount == 24) {* (RGBTRIPLE *) PRGB = * (RGBTRIPLE *) & dwpixel; prgb-> rgbreserved = 0;} // if the bit-count is 32 and the bicompression field is bi_rgb, // Just Use the Pixel Else if (ibitcount == 32 && pdib-> ds.dsbmih.biCompression == bi_rgb) {* prgb = * (rgbquad *) & dwpixel; // Otherwise, use the mask and shift value@ {prg-> rgbred = (byte) ((pdib-> ds.dsbitfields [0] & dwpixel ) >> PDIB-> IRSHIFT [0]) << pdib-> ilshift [0]); prgb-> rgbgreen = (Byte (PDIB-> DS.DSBITFIELDS [1] & dwpixel) >> PDIB-> IRSHIFT [ 1] << PDIB-> Ilshift [1]); PRGB-> RGBBLUE = (Byte) ((PDIB-> DS.DSBITFIELDS [2] & dwpixel) >> PDIB-> Irshift [2]) << pdib-> ilshift [2]);} return true;} / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ----------------------------- Dibsetpixelcolor: Sets the Pixel Color At (x, y) --------- -------------------------------------------------- ------------------ * / Bool Dibsetpixelcolor (HDIB HDIB, INT X, INT Y, RGBQUAD * PRGB) {DWORD DWPIXEL; INT IBITCOUNT; PDIBSTRUCT PDIB = HDIB; // Don't do this function for dibs with color tables iBitCount = DibBitCount (hdib); if (iBitCount <= 8) return FALSE; // The rest is just the opposite of DibGetPixelColorelse if (iBitCount == 24) {* (RGBTRIPLE *) & dwPixel = * (RGBTRIPLE *) prgb; Dwpixel & = 0x00ffffff;} else if (ibitcount == 32 && pdib-> ds.dsbmih.biCompression == bi_rgb) {* (RGBQUAD *) & dwpixel = * prg;} Else {dwpixel = ((dword) prgb-> rgbred >> PDIB-> ilshift [0]) << PDIB-> Irship [0]); DWPIXEL | = ((DWORD) prgb-> rgbgreen >> PDIB-> Ilshift [1]) << PDIB-> Irship [1]); DWPIXEL | = ((DWORD) prgb-> rgbblue >> PDIB-> ilshift [2]) << PDIB-> Irshift [2]);} DibsetPixel (HDIB, X, Y, DWPixel); Return True;} This section dibhelp.c starts from the Dibpixelptr function, which is a metrics that point to the bit ing group with special storing (or partial storage). Recall the PPROW field of the Dibstruct structure, which is a metrics that point to the pattern row site where the DIB is started. In this way, (PDIBSTRUCT) HDIB) -> PPROW) [0] is to point to the index of the leftmost end of DIB, and ((PDIBSTRUCT) HDIB) -> PPROW) [Y] (X * Dibbitcount (HDIB) >> 3) is an indicator of a set of icons located in (x, y). Note that if the status in the DIB cannot be addressed (ie, if the X and Y parameters of the function are negative or relative to the area outside the DIB, the function will return to NULL. This check reduces the execution speed of the function (and all the functions that depend on Dibpixelptr), below I will tell some faster frequencies. DibgetPixel and DibsetPixel functions behind the archives use Dibpixelptr. For 8-bit, 16-bit and 32-bit dib, these functions only record indicators to the appropriate data size, and access the iconic value. For a 1-bit and 4-bit dib, a mask and displacement angle is required. DibgetColor Funel Press the RGBQUAD structure to get a lookup color. For 1-bit, 4-bit and 8-bit dib, this includes using a primitive value to obtain a color from the DIB color table. For 16-bit, 24-bit and 32-bit dib, the primer must be masked and shifted to obtain the RGB color. The DibsetPixel is reversed, which allows setting the iconic value from the RGBQUAD structure. This function is only 16-bit, 24-bit and 32-bit DIB definitions. Establishment and conversion The Dibhelp Part III and the final section shown in the process 16-21 show how to establish a DIB block and how to convert DIB blocks with PACKED DIBs. The third part of the program 16-21 Dibhelp.c file and the last part of Dibhelp.c (Part III) / * ------------------------- ------------------------------------------------- Calculating Shift values from color masks is required by the dibcreatefrominfo function. ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------- / Static Int MasktorsHift (DWORD DWMASK) {ISHIFT; if (dwmask == 0) Return 0; for (iShift = 0;! (dwmask & 1); iShift ) dwmask >> = 1; Return Ishift;} Static Int Masktolshift (DWord dwmask) {ISHIFT; if (dwmask == 0) Return 0; While (! (DWMASK & 1)) DWMASK >> = 1; for (iShift = 0; dwmask & 1; ishift ) dwmask> > = 1; Return 8 - Ishift;} / * -------------------------------------- -------------------------------------- DibcreateFromInfo: All Dib Creation Functions Ultimately Call this One.THIS Function is responsible for calling createdibsection, allocatingmemory for dibstruct, and setting up the row pointer. -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------------------------- * / hdib dibcreatefrominfo BITMAPINFO * pbmi) {BYTE * pBits; DIBSTRUCT * pdib; HBITMAP hBitmap; int i, iRowLength, cy, y; hBitmap = CreateDIBSection (NULL, pbmi, DIB_RGB_COLORS, & pBits, NULL, 0); if (hBitmap == NULL) return NULL; if (null == (PDIB = Malloc (Sizeof (Dibstructure)))) {deleteObject (hbitmap); Return Null;} PDIB-> isignARE = HDIB_SIGNATURE; PDIB-> hbitmap = hbitmap; PDIB-> PBITS = PBITS; GetObject (Hbitmap, Sizeof (Dibsection), & PDIB-> DS); // NOTICE THAT WE CAN NOW Use the Dib Information functions // defined Above. // if the compression is bi_bitfields, Calculate Shifts from masks IF (Dibcompression (PDIB) == bi_bitfields) {for (i = 0; i <3; i ) {pdib-> ilshift [i] = masktolshift (pdib-> ds.dsbitfields [i]); PDIB-> IRSHIFT [ I] = Masktorshift (PDIB-> DS.DSBITFIELDS [I]);}} // if the compression is bi_rgb, but bit-count is 16 or 32, // set the bitfields and the maskselse if (dibcompression (pdib) == bi_rgb) {IF (Dibbitcount (PDIB) == 16) {PDIB-> DS.DSBITFIELDS [0] = 0x00007C00; PDIB-> DS.DSBITFIELDS [1] = 0x000003E0; PDIB-> DS.DSBITFIELDS [2] = 0x0000001F; PDIB-> Irshift [0] = 10; PDIB-> Irshift [1] = 5; PDIB-> Irshift [2] = 0; PDIB-> ilshift [0] = 3; PDIB-> ilshift [1] = 3; PDIB-> ilshift [2] = 3;} else if (dibbitcount (pdib) == 24 || Dibbitcount (PDIB) == 32 ) {PDIB-> DS.DSBITFIELDS [0] = 0x00FF0000; PDIB-> DS.DSBILDS [1] = 0x0000FF00; PDIB-> DS.DSBILDS [2] = 0x000000FF; PDIB-> IRSHIFT [0] = 16; PDIB-> IRSHIFT [1] = 8; PDIB-> IRSHIFT [2] = 0; PDIB-> ilshift [0] = 0; PDIB-> ilshift [1] = 0; PDIB-> ilshift [2] = 0;}} // allocate an array of pointers to each row in the dibcy = dibheight (PDIB) ; if (null == (pdib-> pprow = malloc)))) {free (PDIB); deleteObject (hbitmap); Return Null;} // Initialize am.irowlength = dibrowLength (PDIB); if (pbmi-> bmiheader.biheight> 0) // i i, bottom up {for (y = 0; y / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------- Dibdelete: Free Memory for the Dib Section ------------- -------------------------------------------------- ----------- * / Bool Dibdelete (HDIB HDIB) {Dibstruct * PDIB = HDIB; if (! Dibisvalid (HDIB)) Return False; Free (PDIB-> PPROW); deleteObject (PDIB-> hbitmap); Free (PDIB); Return True;} / * ------------------------------------------------- --------------------------- Dibcreate: Creates An HDIB from expected arguments --------------- -------------------------------------------------- ------------ * / HDIB Dibcreate (int Cx, int Cy, int cbits, int ccolors) {bitmapInfo * pbmi; dword dwinfosize; hdib hdib; int Centries IF (CX <= 0 || CY <= 0 || ((cbits! = 1) && (cbits! = 8) && (cbits! = 16) && (cbits! = 24) && (CBITS! = 32)))))))) {return null;} IF (ccolors! = 0) centries = ccolors; Else IF (cbits <= 8) centries = 1 << cbits; Dwinfosize = sizeof (BitmapInfoHeader) (Centries - 1) * SizeOf (RGBQUAD); IF (NULL == (PBMI = Malloc (dwinfosize))) {Return Null;} ZeromeMory (PBMI, dwinfosize); pbmi-> bmiHeader.biSize = sizeof (BITMAPINFOHEADER); pbmi-> bmiHeader.biWidth = cx; pbmi-> bmiHeader.biHeight = cy; pbmi-> bmiHeader.biPlanes = 1; pbmi-> bmiHeader.biBitCount = cBits; pbmi- > bmiHeader.biCompression = BI_RGB; pbmi-> bmiHeader.biSizeImage = 0; pbmi-> bmiHeader.biXPelsPerMeter = 0; pbmi-> bmiHeader.biYPelsPerMeter = 0; pbmi-> bmiHeader.biClrUsed = cColors; pbmi-> bmiHeader.biClrImportant = 0; HDIB = DibcreateFromInfo (PBMI); Free (PBMI); Return HDIB; / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- DibcopyToinfo: Builds BitmapInfo Structure.used by Dibcopy and DibcopyTodDB ----------- -------------------------------------------------- ---------------- / Static BitmapInfo * DibcopyToinfo (HDIB HDIB) {BitmapInfo * PBMI; INT I, Inumcolors; Rgbquad * Prgb; if (! Dibisvalid (HDIB) Return Null ; // Allocate the memoryif (NULL == (pbmi = malloc (DibInfoSize (hdib)))) return NULL; // Copy the information headerCopyMemory (pbmi, DibInfoHeaderPtr (hdib), sizeof (BITMAPINFOHEADER)); // Copy the possible Color Masks PRGB = (RGBQUAD *) ((BYTE *) PBMI SizeOf (BitmapInfoHeader); IF (Dibmasksize (HDIB)) {CopyMemory (PrGB, Dibmaskptr (HDIB), 3 * SizeOf (DWORD)); prgb = (RGBQUAD *) ((Byte *) PRGB 3 * SizeOf (DWORD));} // Copy The Color TableinumColors = DibnumColors (HDIB); for (i = 0; I / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------- Dibcopy: Creates A New Dib Section from an existing dib section, Possibly swapping the dib width and height .--- -------------------------------------------------- ---------------------- * / HDIB Dibcopy (HDIB HDIBSRC, BOOL FROTATE) {BitmapInfo * PBMI; BYTE * PBITSRC, * PBITSDST; HDIB HDIBDST; (! DibIsValid (hdibSrc)) if return NULL; if (NULL == (pbmi = DibCopyToInfo (hdibSrc))) return NULL; if (fRotate) {pbmi-> bmiHeader.biWidth = DibHeight (hdibSrc); pbmi-> bmiHeader. Biheight = Dibwidth (HDIBSRC); HDIBDST = DibcreateFromInfo (PBMI); Free (PBMI); IF (HDIBDST == Null) Return NULL; // Copy the bits IF (! frotate) {pBitsSrc = dibbitsptr (HDIBSRC); PBITSDST = DibbitSptr (HDIBDST); CopyMemory (Pbitsdst, PbitsSrc, Dibbitssize (HDIBSRC));} Return Hdibdst;} / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- DibcopytopackedDib Is Generally use for saving dibs and for transferring dibs to the clipboard. In the second case, the second Argument shop be set to true so what the meory is allocatedwith the gmem_share flag. -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ------------------------------------------- * / BITMAPINFO * DibCopyToPackedDib (HDIB hdib, BOOL fUseGlobal) {BITMAPINFO * pPackedDib; BYTE * pBits; DWORD dwDibSize; HDC hdcMem; HGLOBAL hGlobal; int iNumColors; PDIBSTRUCT pdib = hdib; RGBQUAD * prgb; if return NULL; // Allocate memory for packed DIBdwDibSize = DibTotalSize (hdib); (DibIsValid (hdib)!) if (fUseGlobal) {hGlobal = GlobalAlloc (GHND | GMEM_SHARE, dwDibSize); pPackedDib = GlobalLock (hGlobal);} else { PPACKEDDIB = Malloc (dwdibsize); if (pPackedDib == NULL) return NULL; // Copy the information headerCopyMemory (pPackedDib, & pdib-> ds.dsBmih, sizeof (BITMAPINFOHEADER)); prgb = (RGBQUAD *) ((BYTE *) pPackedDib sizeof (BITMAPINFOHEADER)) ; // copy the Possible Color Masksif (PDIB-> DS.DSBMIH.Bicompression == Bi_bitfields) {copyMemory (prgb, pdib-> ds.dsbitfields, 3 * sizeof (dword)); prgb = (rgbquad *) ((Byte *) prgb 3 * sizeof (DWORD));} // Copy the color tableif (iNumColors = DibNumColors (hdib)) {hdcMem = CreateCompatibleDC (NULL); SelectObject (hdcMem, pdib-> hBitmap); GetDIBColorTable (hdcMem, 0 , inumcolors, prg); deletedc (hdcmem); PBITS = (PRGB Inumcolors); // Copy The BitscopyMemory (PBITS, PDIB-> PBITS, DibbitsSize (PDIB)); // if Last Argument is true, UNLOCK GLOBAL MEMORY BLOCK AND // Cast It To Pointer In preparation for returnif (fuseglobal) {globalunlock (hglobal); ppackedDib = (bitmapInfo *) hglobal;} return ppackedDIB; / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ------------------------- DibcopyFromPackedDib Is Generally Used for Pasting Dibs from The Clipboard. ------------- -------------------------------------------------- --------- * / HDIB DibcopyFromPackedDib (BitmapInfo * PPackedDib) {byte * Pbits; DWORD DWINFOSIZE, DWMASKSIZE, DWCOLORSIZE; INT IBITCOUNT; PDIBSTRUCT PDIB; // Get the size of the information header and do validity checkdwInfoSize = pPackedDib-> bmiHeader.biSize;!!!! If (dwInfoSize = sizeof (BITMAPCOREHEADER) && dwInfoSize = sizeof (BITMAPINFOHEADER) && dwInfoSize = sizeof (BITMAPV4HEADER) && dwInfoSize = sizeof (BITMAPV5HEADER )) {RETURN NULL;} // Get the Possible Size of the Color Masks if (dwInfoSize == sizeof (BITMAPINFOHEADER) && pPackedDib-> bmiHeader.biCompression == BI_BITFIELDS) {dwMaskSize = 3 * sizeof (DWORD);} else {dwMaskSize = 0;} // Get the size of the color tableif (dwInfoSize == Sizeof (Bitmapcorehead) {ibitcount = ((BitmapCorehead *) PPACKEDDIB) -> bcbitcount; IF (ibitcount <= 8) {dwcolorsize = (1 << ibitcount) * sizeof (rgbtriple);} else // all Non-OS / 2 Compatible Dibs {if (PPACKEDDIB-> Bmiheader.Biclrused> 0 ) {dwColorSize = pPackedDib-> bmiHeader.biClrUsed * sizeof (RGBQUAD);} else if (pPackedDib-> bmiHeader.biBitCount <= 8) {dwColorSize = (1 << pPackedDib-> bmiHeader.biBitCount) * sizeof (RGBQUAD); } else {dwColorSize = 0;}} // Finally, get the pointer to the bits in the packed DIBpBits = (BYTE *) pPackedDib dwInfoSize dwMaskSize dwColorSize; // Create the HDIB from the packed-DIB pointerpdib = DibCreateFromInfo ( PPACKEDDIB); // Copy The Pixel BitscopyMemory (PDIB-> PBITS, PBITS, DIBBITSSIZE (PDIB)); Return PDIB;} / * --------------------- -------------------------------------------------- ----- DibfileLoad: Creates A Dib Section from a dib file ----------------------------------- ------------------------------------------ / HDIB DibfileLoad (const tchar * SZFileName) {BitmapFileHeader BMFH; BitmapInfo * PBMI; BOOL BSUCCESS; DWORD Dwinfosize, dwbitssize, dwbytesread; HDIB HDIB; // Open the file: read access, prohibit Write Access hFile = CreateFile (szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); if (hFile == INVALID_HANDLE_VALUE) return NULL; // Read in the BITMAPFILEHEADERbSuccess = ReadFile (hFile, & bmfh, sizeof (BITMAPFILEHEADER), & dwBytesRead, NULL ); IF (! bsuccess | = sizeof (bitmapfilehead)) || (BMFH.BFTYPE! = * (Word *) "BM")) {closeHandle (HFILE); Return null;} // allocate memory for the information structure & read it indwInfoSize = bmfh.bfOffBits - sizeof (BITMAPFILEHEADER); if (NULL == (pbmi = malloc (dwInfoSize))) {CloseHandle (hFile); return NULL;} bSuccess = ReadFile (hFile, pbmi, dwInfoSize, & dwBytesRead , NULL); if (! Bsuccess || (dwbytesread! = Dwinfosize)) {CloseHandle (HFILE); Free (PBMI); return null;} // create the dibhdib = dibcreateFromInfo (PBMI); Free (PBMI); if (hDib == NULL) {CloseHandle (hFile); return NULL;} // Read in the bitsdwBitsSize = bmfh.bfSize - bmfh.bfOffBits; bSuccess = ReadFile (hFile, ((PDIBSTRUCT) hDib) -> pBits, dwBitsSize, & dwbytesread, null; closehandle (HFILE); if (! bsuccess || (dwbytesread! = dwbitssize) {Dibdelete (HDIB); Return null;} return null;} return / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------- Dibfilesave: Saves a Dib Section to a file --------------- -------------------------------------------------- ----------- * / Bool Dibfilesave (HDIB HDIB, Const Tchar * SzFileName) {BitmapFileHeader BMFH; BitmapInfo * PBMI; BOOL BSUCCESS; DWORD DWTOTALSIZE, DWBYTESWRITEN; Handle Hfile; hFile = CreateFile (szFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) return FALSE; dwTotalSize = DibTotalSize (hdib); bmfh.bfType = * (WORD *) "BM"; bmfh .BFSIZE = SizeOf (BitmapfileHeader) DWTOTALSIZE; BMFH.BFRESERVED1 = 0; bmfh.bfreserved2 = 0; bmfh.bfoffbits = BMFH.BFSIZE - DibbitsSize (HDIB); // Write the BitmapfileHeaderbsuccess = Writefile (HFile, & BMFH, Sizeof (BitmapfileHeader), & DWBYTESWRITEN, NULL if (bSuccess || (dwBytesWritten = sizeof (BITMAPFILEHEADER))!!) {CloseHandle (hFile); DeleteFile (szFileName); return FALSE;} // Get entire DIB in packed-DIB formatif (NULL == (pbmi = DibCopyToPackedDib ( hdib, FALSE))) {CloseHandle (hFile); DeleteFile (szFileName); return FALSE;} // Write out the packed DIBbSuccess = WriteFile (hFile, pbmi, dwTotalSize, & dwBytesWritten, NULL); CloseHandle (hFile); free (pbmi ); IF (! bsuccess || (dwbytesize)) {deletefile (szfilename); return false;} return true;} / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------- DibcopyToddb: for more effect screen displays ---------------- -------------------------------------------------- ------- * / hbitmap dibcopytoddb (HDIB HDIB, HWND HWND, HPALETTE HPALETTE) {BitmapInfo * PBMI; HBitmap HbitMap; HDC HDC; IF (! Dibisvalid (HDIB)) Return NULL; if (NULL == (PBMI = DibcopyToinfo (HDIB)) Return NULL; HDC = Getdc (HWND); if (HPALETTE) {SelectPalette (HPALETTE, FALSE) ;RIZEPALETTE (HDC);} hbitmap = createdibitmap (HDC, DibinfoHeaderptr (HDIB), CBM_INIT, Dibbitsptr (HDIB), PBMI, DIB_RGB_COLORS); ReleaseDC (HWND, HDC); Free (PBMI); Return HbitMap;} This section of the Dibhelp.c file begins with two small fift, which gives the left and right shift value according to the color mask of the 16-bit and 32-bit DIB. These functions are described in Chapter 15 "Color Mask" section. The DibcreateFromInfo Funel is the only call createDibsection in Dibhelp and configure the memory of the memory structure. All other established and replicated functions are repeated this one. DibcreateFromInfo unique parameters are indicators to the BitmapInfo structure. The color table of this structure must exist, but it does not have to fill with a valid value. After calling createDibSECTION, the function will initialize all fields of the Dibstruct structure. Note that when setting the value of the PPROW field of the Dibstruct structure (pointing to the DIB line site), the DIB has a different storage mode of the bottom and upward. The elements at the beginning of PPROW are the top row of DIB. DIBDelete deletes a dot matrix created in DibcreateFromInfo while releasing the memory configured in this function. Dibcreate may be more like a Volume from an application call than DibcreateFromInfo. The first three parameters provide a width, height, and a number of digits per status. The last parameter can be set to 0 (the internal size of the color table), or set to be non-0 (indicating a color table smaller than the color table required for each status). Dibcopy creates a new DIB block based on the existing DIB block, and the memory is configured with the BitmapInfo structure with the DibcreateInfo, but also filled out all the information. A BOOL parameter of the DIBCOPY function indicates whether the width and height of the DIB is exchanged when the new DIB is established. We will see the usage of this function later. The use of DibcopyTopackedDib and DibcopyFromPackedDIB Functions is usually related to passing DIB through the scrapbook. DibfileLoad is established from DIB files; DibfileSave functions store data to DIB files. Finally, the DibcopyTodDB function establishes a GDI dot matrix object according to DIB. Note that the function requires the current color display code and code of the program. The program window code is used to obtain the contents of the selection and display the color tray. Only in this way, the function can call CREATEDIBITMAP. This is displayed in ShowDIB7 in front of this chapter. Dibhelp header file and huge set Dibhelp.h The header file is shown in the formula 16-22. Co-style 16-22 Dibhelp.h file Dibhelp.h / * ------------------------------------- ------------------------------------- Dibhelp.h Header File for Dibhelp.c ---- -------------------------------------------------- ---------------------- * / typedef void * HDIB; // Functions in DIBHELP.CBOOL DibIsValid (HDIB hdib); HBITMAP DibBitmapHandle (HDIB hdib); int DibWidth (HDIB hdib); int DibHeight (HDIB hdib); int DibBitCount (HDIB hdib); int DibRowLength (HDIB hdib); int DibNumColors (hDIB hdib); DWORD DibMask (hDIB hdib, int i); int DibRShift (hDIB hdib, int i); int DibLShift (hDIB hdib, int i); int DibCompression (hDIB hdib); BOOL DibIsAddressable ( hDIB hdib); DWORD DibInfoHeaderSize (hDIB hdib); DWORD DibMaskSize (hDIB hdib); DWORD DibColorSize (hDIB hdib); DWORD DibInfoSize (hDIB hdib); DWORD DibBitsSize (hDIB hdib); DWORD DibTotalSize (hDIB hdib); BITMAPINFOHEADER * DibInfoHeaderPtr ( HDIB hdib); DWORD * DibMaskPtr (HDIB hdib); void * DibBitsPtr (HDIB hdib); BOOL DibGetColor (HDIB hdib, int index, RGBQUAD * prgb); BOOL DibSetColor (HDIB hdib, int index, RGBQUAD * prgb); BYTE * Dibpixelptr (HDIB HDIB, INT X, INT Y); DWORD DibgetPixel (HDIB HDIB, INT X, INT Y); Bool Dibsetpixel (HDIB HDIB, INT X, INT Y, DWORD DWPIXEL); BOOL D ibGetPixelColor (HDIB hdib, int x, int y, RGBQUAD * prgb); BOOL DibSetPixelColor (HDIB hdib, int x, int y, RGBQUAD * prgb); HDIB DibCreateFromInfo (BITMAPINFO * pbmi); BOOL DibDelete (HDIB hdib); HDIB DibCreate (int cx, int cy, int cBits, int cColors); hDIB DibCopy (hDIB hdibSrc, BOOL fRotate); BITMAPINFO * DibCopyToPackedDib (hDIB hdib, BOOL fUseGlobal); hDIB DibCopyFromPackedDib (BITMAPINFO * pPackedDib); hDIB DibFileLoad (const TCHAR * szFileName ); Bool Dibfilesave (HDIB HDIB, Const Tchar * SzFileName); HBitmap DibcopyTodDB (HDIB HDIB, HWND HWND, HPALETTE HPALETTE); HDIB DibcreateFromDDB (Hbitmap Hbitmap); / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------- Quickie No-Bounds-Checked Pixel gets and sets ------------- -------------------------------------------------- -------------- * / # Define Dibpixelptr1 (HDIB, X, Y) (((* (pbyte **) HDIB) [Y]) ((x) >> 3) #define dibpixelptr4 (HDIB, X, Y) (((* (pbyte **) hdib) [Y]) ((x) >> 1) # define dibpixelptr8 (hdib, x, y) ((* (PBYTE **) HDIB) [Y]) (h, xel) / ((Word *) ((* (pbyte **) HDIB [Y]) (x ) * 2)) #define dibpixelptr24 (hdib, x, y) / ((RGBTRIPLE *) ((* (pbyte **) HDIB) [Y]) (x) * 3) # define dibpixelptr32 (HDIB, X, Y) / ((DWORD *) ((* (pbyte **) hdib) [Y]) (x) * 4)))) #define DibgetPixel1 (HDIB, X, Y) / (0x01 & (* Dibpixelptr1 (HDIB, X, Y) >> (7 - ((x) & 7)))))))))) #define DibgetPixel4 (HDIB, X, Y) / (0x0f & (* Dibpixelptr4 (HDIB, X, Y) >> ((x) & 1? 0: 4)))))))) #define DibgetPixel8 (HDIB, X, Y) (* Dibpixelptr8 (HDIB, X, Y)) # define DibgetPixel16 (HDIB, X, Y) (* Dibpixelptr16 (HDIB, X, Y)) # define DibgetPixel24 (HDIB, X, Y) (* Dibpixelptr24 (HDIB, X, Y)) # define DibgetPixel32 (HDIB, X, Y) (* Dibpixelptr32 (HDIB, X, Y)) #define dibsetpixel1 (HDIB, X, Y, P) / (* Dibpixelptr1 (HDIB, X, Y) & = ~ (1 << (7- ((x) & 7))))), / (* Dibpixelptr1 HDIB, X, Y) | = ((P) << (7 - ((x) & 7)))))))))))) #define dibsetpixel4 (HDIB, X, Y, P) / (* Dibpixelptr4 (HDIB, X, Y) & = (0x0f << ((x) & 1? 4: 0))), / (* DibpixElPtr4 (HDIB , X, Y) | = ((p) << ((x) & 1? 0: 4)))))))))))))) #define dibsetpixel8 (HDIB, X, Y, P) (* Dibpixelptr8 (HDIB, X, Y) = P #define dibsetpixel16 (HDIB, X, Y, P) (* Dibpixelptr16 (HDIB, X, Y) = P) #define dibsetpixel24 (HDIB, X, Y, P) (* Dibpixelptr24 (HDIB, X, Y) = P) #define dibsetpixel32 (HDIB, X, Y, P) (* Dibpixelptr32 (HDIB, X, Y) = P) This header file defines HDIB as empty indicators (VOID *). The application does not need to know the internal structure of the structure referred to in HDIB. This header file also includes instructions in all functions in dibhelp.c, and some huge gathering - very special gauges. If you look at Dibpixelptr, Dibgetpixel, and Dibsetpixel in dibhelp.c, and try to improve their execution speed performance, you will see two possible solutions. The first, you can delete all check protection and believe that the application does not use invalid parameters call fifth. You can also delete some of the functions, such as DibbitCount, and use the indicators inside the Dibstruct structure to get information directly. Improve the implementation speed performance Another less obvious method is to delete all processing methods for each status element, simultaneously separating different DIB functions - such as DibgetPixel1, DibgetPixel4, DibgetPixel8, etc. The next optimization step is to delete the entire functional call, and the processing action is merged through the inline function or the huge set. Dibhelp.h uses a mason method. It proposes three sets of gauges based on Dibpixelptr, DibgetPixel and Dibsetpixel. These giants have clearly corresponding to the number of special grain bits. Dibble DIBBLE, as shown in the formula 16-23, using Dibhelp functions and gauge work. Although dibble is the longest program in this book, it is only a rough example of some jobs, which can be found in a simple digital image processing program. The significant improvement to DIBLLE is converted into multiple file interfaces (MDI: Multiple Document Interface), and we will learn about multiple file interfaces in Chapter 19. Co-style 16-23 DibbleDibble.c / * ------------------------------------------------------- -------------------------------- Dibble.c - Bitmap and Palette Program (c) Charles Petzold, 1998 -------------------------------------------------- --------------------------- * / #include #define wm_user_setscrolls (WM_USER 1) #define WM_USER_DELETEDIB (WM_USER 2) #define WM_USER_DELETEPAL (WM_USER 3) #define WM_USER_CREATEPAL (WM_USER 4) LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); TCHAR szAppName [] = TEXT ( "Dibble"); int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {HACCEL hAccel; HWND hwnd; MSG msg ; WNDCLASS wndclass; wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor (NULL, IDC_ARROW); WNDCLASS.HBRBACKGROUND = (HBrush) getStockObject (White_brush); WNDCLASS.LPSZMENUNAME = SZAPPNAME; WNDCLASS.LPSZCLASSNAME = Szappname; IF (! RegisterClass (& Wndclass)) {MessageBox (Null, Text ("This Program Requires Windows NT!"), SZAPPNAME, MB_ICONERROR); RETURN 0;} hwnd = CreateWindow (szAppName, szAppName, WS_OVERLAPPEDWINDOW | WM_VSCROLL | WM_HSCROLL, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ShowWindow (hwnd, icmdshow); UpdateWindow (HWND); Haccel = loadingAccelerators (Hinstance, Szappname); While (GetMessage (& MSG, NULL, 0, 0)) {if (! TranslateMcelerator (& MSG)) {TranslateMessage (& MSG); DispatchMessage (& MSG);}} Return Msg.wParam;} / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- DISPLAYDIB: DISPLAYS or Stretched Depending on Menu Selection -------- -------------------------------------------------- ------------------- * / int DisplayDib (HDC hdc, HBITMAP hBitmap, int x, int y, int cxClient, int cyClient, WORD wShow, BOOL fHalftonePalette) {BITMAP bitmap; HDC hdcMem; int cxBitmap, cyBitmap, iReturn; GetObject (hBitmap, sizeof (BITMAP), & bitmap); cxBitmap = bitmap.bmWidth; cyBitmap = bitmap.bmHeight; SaveDC (hdc); if (fHalftonePalette) SetStretchBltMode (hdc, HALFTONE); elseSetStretchBltMode (hdc, COLORONCOLOR); hdcMem = CreateCompatibleDC (hdc); SelectObject (hdcMem, hBitmap ); Switch (wshow) {copy IDM_SHOW_NORMAL: IF (FHALFTONEPALETTTE) IRETURN = Stretchblt (HDC, 0, 0, Min (CxClient, CXbitmap - x), MIN (Cyclient, Cybitmap - Y), HDCMEM, X, Y, MIN (CxClient, CXBitmap - x), min (cyclient, cybitmap - y), srccopy; elseiReturn = Bitblt (HDC, 0, 0, Min (CxClient, CXbitmap - x), Min (Cyclient, Cybitmap - Y), HDCMEM, X, Y , SRCCOPY); break; case IDM_SHOW_CENTER: if (fHalftonePalette) iReturn = StretchBlt (hdc, (cxClient - cxBitmap) / 2, (cyClient - cyBitmap) / 2, cxBitmap, cyBitmap, hdcMem, 0, 0, cxBitmap, cyBitmap, SRCCOPY ); elseiReturn = Bitblt (CxClient - cxbitmap) / 2, Cyclient - cybitmap / 2, cxbitmap, cybitmap, hdcmem, 0, 0, srcopy; break; case idm_show_stretch: Ireturn = stretchblt (HDC, 0, 0 , CxClient, Cyclient, HDCMEM, 0, 0, CXBitmap, Cybitmap, Srccopy; case IDM_SHOW_ISOSTRETCH: SetMapMode (hdc, MM_ISOTROPIC); SetWindowExtEx (hdc, cxBitmap, cyBitmap, NULL); SetViewportExtEx (hdc, cxClient, cyClient, NULL); SetWindowOrgEx (hdc, cxBitmap / 2, cyBitmap / 2, NULL); SetViewportOrgEx (hdc , cxclient / 2, cyclient / 2, null; IReturn = stretchblt (HDC, 0, 0, CXbitmap, Cybitmap, HDCMEM, 0, 0, CXbitmap, Cybitmap, Srccopy; Break;} deletedc (hdcmem); restoredc (HDC, -1); Return IReturn; / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------- Dibfliphorizontal: Calls Non-Optimized Dibsetpixel and Dibgetpixel -------------- -------------------------------------------------- ----------- * / HDIB Dibfliphorizontal (HDIB HDIBSRC) {HDIB HDIBDST; INT CX, CY, X, Y; IF (! Dibisaddressable (HDIBSRC)) Return NULL; if (null == (HDIBDST = Dibcopy (HDIBSRC, FALSE))) Return NULL; CX = Dibwidth (HDIBSRC); CY = DibHeight (HDIBSRC); for (x = 0; X Return hdibdst;} / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------- DibrotaTeright: Calls Optimized Dibsetpixelx and DibgetPixelx ---------------------------------------------- -------------------------------------------------- ----------- * / HDIB Dibrotateright (HDIB HDIBSRC) {HDIB HDIBDST; INT CX, CY, X, Y; IF (! dibisaddressable (hdibsrc)) Return NULL; IF (NULL == (HDIBDST = Dibcopy (HDIBSRC, TRUE)) Return NULL; CX = Dibwidth (HDIBSRC); CY = DibHeight (HDIBSRC); Switch (DibbitCount (HDIBSRC)) {case 1: for (x = 0; x Case 4: for (x = 0; x Case 8: for (x = 0; x Case 32: for (x = 0; x / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ------------------------ Palettemenu: Uncheck and Check Menu Item on Palette Menu ---------------- -------------------------------------------------- -------- * / Void PaletteMenu (HMENU HMENU, WORD WITEMNEW) {static word witem = idm_pal_none; checkmenuitem (HMENU, WITEM, MF_UNCHECKED); WITEM = WITEMNEW; CheckMenuItem (HMENU, WITEM, MF_CHECKED);} LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {static BOOL fHalftonePalette; static DOCINFO di = {sizeof (DOCINFO), TEXT ( "Dibble: Printing")}; static HBITMAP hBitmap; static HDIB hdib; static hMENU hMenu; static HPALETTE hPalette; static int cxClient, cyClient, iVscroll, iHscroll; static OPENFILENAME ofn; static PRINTDLG printdlg = {sizeof (PRINTDLG)}; static TCHAR szFileName [MAX_PATH], szTitleName [MAX_PATH]; static TCHAR szFilter [] = Text ("Bitmap Files (* .BMP) / 0*.BMP/0") Text ("All files (*. *) / 0 *. * / 0/0"); static tchar * szcompression [] = {Text ("Bi_RGB"), Text ("Bi_RLE8"), Text ("Bi_RLE4"), Text ("Bi_bitfields"), Text ("UnkNown")}; static word wshow = idm_show_normal; bool fsuccess; Byte * Pglobal; HDC HDC HDC HDC HDC HDC HDC HDC HDC HDC , hdcPrn; hGLOBAL hGlobal; HDIB hdibNew; int iEnable, cxPage, cyPage, iConvert; PAINTSTRUCT ps; SCROLLINFO si; TCHAR szBuffer [256]; switch (message) {case WM_CREATE: // Save the menu handle in a static variable HMENU = GetMenu (hwnd); // Initialize The OpenFileName Structure for the File Open // And File Save Dialog Boxes. ofn.lStructSize = sizeof (OPENFILENAME); ofn.hwndOwner = hwnd; ofn.hInstance = NULL; ofn.lpstrFilter = szFilter; ofn.lpstrCustomFilter = NULL; ofn.nMaxCustFilter = 0; ofn.nFilterIndex = 0; ofn.lpstrFile = szFileName ; ofn.nMaxFile = MAX_PATH; ofn.lpstrFileTitle = szTitleName; ofn.nMaxFileTitle = MAX_PATH; ofn.lpstrInitialDir = NULL; ofn.lpstrTitle = NULL; ofn.Flags = OFN_OVERWRITEPROMPT; ofn.nFileOffset = 0; ofn.nFileExtension = 0; ofn .lpstrDefExt = TEXT ( "bmp"); ofn.lCustData = 0; ofn.lpfnHook = NULL; ofn.lpTemplateName = NULL; return 0; case WM_DISPLAYCHANGE: SendMessage (hwnd, WM_USER_DELETEPAL, 0, 0); SendMessage (hwnd, WM_USER_CREATEPAL , True, 0); Return 0; Case WM_SIZE: // Save The Client Area Width and Height In Static Variables. CxClient = loword (LPARAM); cyclient = HiWord (LPARAM); wParam = FALSE; // fall through // WM_USER_SETSCROLLS: Programmer-defined Message // Set the scroll bars If the display mode is not normal, // make them invisible If wParam is TRUE, reset the // scroll bar position!.. . case WM_USER_SETSCROLLS: if (! hdib == NULL || wShow = IDM_SHOW_NORMAL) {si.cbSize = sizeof (SCROLLINFO); si.fMask = SIF_RANGE; si.nMin = 0; si.nMax = 0; SetScrollInfo (hwnd, SB_VERT, & Si, True); Setscrollinfo (HWND, SB_HORZ, & SI, TRUE);} else {//first the Vertical Scroll Si.cbsize = sizeof (scrollinfo); si.fmask = SIF_ALL; Getscrollinfo (hwnd, sb_vert, & si); si.nmin = 0; si.nmax = dibheight (hdib); si.npage = cyclient; if ((Bool) wparam si.npos = 0; SetscrollInfo (HWND, SB_VERT, & SI, TRUE); GetScrollInfo (HWND, SB_VERT, & SI); ivscroll = si.npos; // THEN The Horizontal Scroll Getscrollinfo (hwnd, sb_horz, & si); si.nmin = 0; si.nmax = dibwidth (HDIB); si.npage = cxclient; if ((BOOL) wparam) si.npos = 0; Setscrollinfo (HWND, SB_HORZ, & SI, TRUE); GetScrollInfo (HWND, SB_HORZ, & SI); Ihscroll = Si.NPOS;} Return 0; // WM_VSCROLL: VERTICALLY SCROLL THE DIB Case WM_VSCROLL: Si.cbsize = SizeOf (ScrollInfo); Si.fmask = Sif_all; GetScrollInfo (HWND, SB_VERT, & S); ivscroll = si.npos; Switch (WPARAM) {CASE SB_LINEUP: Si.NPOS - = 1; Break; Case Sb_Linedown: Si.npos = 1; Break; Case Sb_pageup: Si.npos - = Si.Npage; Break; Case Sb_Pagedown: Si .nPos = si.nPage; break; case SB_THUMBTRACK: si.nPos = si.nTrackPos; break; default: break;} si.fMask = SIF_POS; SetScrollInfo (hwnd, SB_VERT, & si, TRUE); GetScrollInfo (hwnd, SB_VERT & Si); IF (Si.NPOS! = ivscroll) {scrollwindow (hwnd, 0, ivscroll - si.npos, null, null); ivscroll = si.npos; UpdateWindow (hwnd);} return 0; // WM_HSCROLL: Horizontally Scroll The Dib Case WM_HSCROLL: Si.cbsize = SizeOf (ScrollInfo); Si.fmask = Sif_all; GetScrollInfo (Hwnd, Sb_horz, & Si); Ihscroll = Si.NPOS; Switch (WPARAM) {CASE SB_LINELEFT: SI.NPOS - = 1; Break; Case SB_Lineright: Si.NPOS = 1; Break; Case Sb_pageleft: Si.NPOS - = Si.Npage; Break; Case Sb_PAgeright: Si .npos = si.npage; break; case sb_thumbtrack: si.npos = si.ntrackpos; brefault: Break; Si.fmask = sif_pos; setscrollinfo (hwnd, sb_horz, & si, true); GetScrollInfo (hwnd, sb_horz, & Si); IF (Si.NPOS! = IHScroll) {scrollwindow (hwnd, ihscroll - si.npos, 0, null, null); ihscroll = Si.NPOS; UPDATEWINDOW (HWND);} return 0; // WM_INITMENUPOPUP: enable or gray menu Items case WM_INITMENUPOPUP: if (hdib) iEnable = MF_ENABLED; elseiEnable = MF_GRAYED; EnableMenuItem (hMenu, IDM_FILE_SAVE, iEnable); EnableMenuItem (hMenu, IDM_FILE_PRINT, iEnable); EnableMenuItem (hMenu, IDM_FILE_PROPERTIES, iEnable); EnableMenuItem (hMenu, IDM_EDIT_CUT, iEnable) ENABLEMENUITEM (HMENU, IDM_EDIT_COPY, IENABLE); EnableMenuItem (HMENU, IDM_EDIT_DELETE, IENABLE); INABLE = MF_ENABLED; Elseienable = mf_grayed; EnableMenuItem (hMenu, IDM_EDIT_ROTATE, iEnable); EnableMenuItem (hMenu, IDM_EDIT_FLIP, iEnable); EnableMenuItem (hMenu, IDM_CONVERT_01, iEnable); EnableMenuItem (hMenu, IDM_CONVERT_04, iEnable); EnableMenuItem (hMenu, IDM_CONVERT_08, iEnable); EnableMenuItem (hMenu, IDM_CONVERT_16 , INableMenuitem (HMENU, IDM_CONVERT_24, INABLE); EnableMenuItem (HMENU, IDM_CONVERT_32, IENABLE); switch (DibBitCount (hdib)) {case 1: EnableMenuItem (hMenu, IDM_CONVERT_01, MF_GRAYED); break; case 4: EnableMenuItem (hMenu, IDM_CONVERT_04, MF_GRAYED); break; case 8: EnableMenuItem (hMenu, IDM_CONVERT_08, MF_GRAYED); break; case 16: EnableMenuItem (hMenu, IDM_CONVERT_16, MF_GRAYED); break; case 24: EnableMenuItem (hMenu, IDM_CONVERT_24, MF_GRAYED); break; case 32: EnableMenuItem (hMenu, IDM_CONVERT_32, MF_GRAYED); break;} IF (HDIB && Dibcolorsize (HDIB)> 0) INABLE = MF_ENABED; Elseienable = MF_GRAYED EnableMenuItem (hMenu, IDM_PAL_DIBTABLE, iEnable); if (DibIsAddressable (hdib) && DibBitCount (hdib)> 8) iEnable = MF_ENABLED; elseiEnable = MF_GRAYED; EnableMenuItem (hMenu, IDM_PAL_OPT_POP4, iEnable); EnableMenuItem (hMenu, IDM_PAL_OPT_POP5, iEnable); EnableMenuItem (hMenu, IDM_PAL_OPT_POP6, iEnable); EnableMenuItem (hMenu, IDM_PAL_OPT_MEDCUT, iEnable); EnableMenuItem (? hMenu, IDM_EDIT_PASTE, IsClipboardFormatAvailable (CF_DIB) MF_ENABLED: MF_GRAYED); Return 0; // WM_COMMAND: Process All Menu Commands. Case WM_COMMAND: ICONVERT = 0; Switch (loword (wparam) {copy idm_file_open: // Show the file open dialog box IF (! getopenfilename (& off)) Return 0; //iff there's an existing dib and paste, delete them SendMessage (hwnd, wm_user_deletedib, 0, 0); // load the dib Into memory SetCursor (LoadCursor (NULL, IDC_WAIT); showcursor (TRUE); HDIB = DibfileLoad (SZFileName); Showcursor (False); SetCursor (LoadCursor (NULL, IDC_ARROW); // reset the scroll bars SendMessage (hwnd, wm_user_setscrolls, true, 0); // Create the Palette and DDB SendMessage (hwnd, wm_user_createpal, true, 0); IF (! hdib) {MessageBox (HWND, Text ("Cannot Load Dib File!"), Szappname, MB_OK | MB_ICONEXCLAMATION;} invalidateRect (HWND, NULL, TRUE); RETURN 0; Case idm_file_save: // show the file save dialog box IF (! GetsaveFileName (& OFN)) RETURN 0; // save the dib to memory SetCursor (LoadCursor (NULL, IDC_WAIT); showcursor (TRUE); Fsuccess = dibfilesave (HDIB, SZFileName); Showcursor (False); SetCursor (LoadCursor (NULL, IDC_ARROW); IF (! fsuccess) MessageBox (HWND, Text ("Cannot Save Dib File!"), Szappname, MB_OK | MB_ICONEXCLAMATION; RETURN 0; Case IDM_File_Print: if (! hdib) Return 0; // Get Printer DC Printdlg.flags = PD_RETURNDC | PD_NOPAGENUMS | PD_NOSELECTION; IF (! Printdlg (& PrintDLG) Return 0; IF (NULL == (HDCPRN = PrintDLG.HDC)) {MessageBox (HWND, Text ("Cannot Obtain Printer DC"), Szappname, MB_ICONEXCLAMATION | MB_OK; RETURN 0;} // Check if the Printer Can Print Bitmaps if ((RC_BITBLT & GetDeviceCaps (hdcPrn, RASTERCAPS))!) {DeleteDC (hdcPrn); MessageBox (hwnd, TEXT ( "Printer can not print bitmaps"), szAppName, MB_ICONEXCLAMATION | MB_OK); return 0;} // Get size of Printable area of page CXPAGE = getDeviceCaps (HDCPRN, HORZRES); cypage = getDeviceCaps (HDCPRN, Vertres); Fsuccess = false; // send the dib to the printer SetCursor (LoadCursor (NULL, IDC_WAIT); showcursor (TRUE); IF (STARTDOC (HDCPRN, & DI)> 0) && (STARTPAGE (HDCPRN)> 0)) {DisplayDib (HDCPRN, DibbitMapHandle (HDIB), 0, 0, CXPAGE, CYPAGE, WSHOW, FALSE; IF (Endpage (HDCPRN )> 0) {fsuccess = true; enddoc (hdcprn);}}} showcursor (false); setCursor (NULL, IDC_ARROW); Deletedc (HDCPRN); IF (! fsuccess) MessageBox (HWND, Text ("Could Not Print Bitmap"), SZAPPNAME, MB_ICONEXCLAMATION | MB_OK; RETURN 0; Case IDM_File_Properties: if (! hdib) Return 0; WSPrintf (Szbuffer, Text ("Pixel Width: / T% I / N") Text ("Pixel Height: / T% I / N") Text ("BITS Per Pixel: / T% I / N") Text (" Number of Colors: / T% I / N ") TEXT (" Compression: / T% S / N "), Dibwidth (HDIB), Dibheight (HDIB), Dibbit (HDIB), Dibnumcolors (HDIB), SZCompression [min 3, Dibcompression (HDIB)]); MessageBox (hwnd, szbuffer, szappname, MB_ICONEXCLAMATION | MB_OK); RETURN 0; CASE IDM_APP_EXIT: SendMessage (hwnd, wm_close, 0, 0); return 0; case IDM_EDit_copy: case IDM_EDit_cut: if (! (hglobal = dibcopytopackedDib (hglobal = dibcopytopackedDib (HDIB, TRUE)) RETURN 0; OpenClipboard (hwnd); EmptyClipboard (); setClipboardData (CF_DIB, HGLOBAL); CloseClipboard (); IF (WPARAM) == IDM_EDIT_COPY) RETURN 0; // Fall Through for IDM_EDIT_CUTCASE IDM_EDIT_DELETE: SendMessage (hwnd, wm_user_deletedib, 0, 0); InvalidateERECT (HWND, NULL, TRUE); Return 0; Case IDM_EDIT_PASTE: OpenClipboard (hwnd); Hglobal = getClipboardData (cf_dib); pglobal = Globalock (Hglobal); // if there's an existing dib and paste, delete the .///////////////////////////// ' IF (pglobal) {sendMessage (hwnd, wm_user_deletedib, 0, 0); hdib = dibcopyFromPackedDib (BitmapInfo *) pglobal); sendMessage (hwnd, wm_user_createpal, true, 0);} GlobalUnlock (Hglobal); Closeclipboard (); // Reset The Scroll Bars SendMessage (hwnd, wm_user_setscrolls, true, 0); InvalidateRect (HWND, NULL, TRUE); RETURN 0; case IDM_EDIT_ROTATE: if (hdibNew = DibRotateRight (hdib)) {DibDelete (hdib); DeleteObject (hBitmap); hdib = hdibNew; hBitmap = DibCopyToDdb (hdib, hwnd, hPalette); SendMessage (hwnd, WM_USER_SETSCROLLS, TRUE, 0); InvalidateRect (HWND, NULL, TRUE);} else {MessageBox (HWND, Text ("Not Enough Memory", Szappname, MB_OK | MB_ICONEXCLAMATION);} Return 0; case IDM_EDIT_FLIP: if (hdibNew = DibFlipHorizontal (hdib)) {DibDelete (hdib); DeleteObject (hBitmap); hdib = hdibNew; hBitmap = DibCopyToDdb (hdib, hwnd, hPalette); InvalidateRect (hwnd, NULL, TRUE);} else { MessageBox (Hwnd, Text ("Not Enough Memory", Szappname, MB_OK | MB_ICONEXCLAMATION;} Return 0; case IDM_SHOW_NORMAL: case IDM_SHOW_CENTER: case IDM_SHOW_STRETCH: case IDM_SHOW_ISOSTRETCH: CheckMenuItem (hMenu, wShow, MF_UNCHECKED); wShow = LOWORD (wParam); CheckMenuItem (hMenu, wShow, MF_CHECKED); SendMessage (hwnd, WM_USER_SETSCROLLS, FALSE, 0); InvalidateRect ( HWND, NULL, TRUE; RETURN 0; case IDM_CONVERT_32: iConvert = 8; case IDM_CONVERT_24: iConvert = 8; case IDM_CONVERT_16: iConvert = 8; case IDM_CONVERT_08: iConvert = 4; case IDM_CONVERT_04: iConvert = 3; case IDM_CONVERT_01: iConvert = 1; SetCursor ( LoadCursor (NULL, IDC_WAIT); showcursor (true); HDIBNEW = Dibconvert (HDIB, ICONVERT); Showcursor (False); SetCursor (LoadCursor (NULL, IDC_ARROW); if (hdibNew) {SendMessage (hwnd, WM_USER_DELETEDIB, 0, 0); hdib = hdibNew; SendMessage (hwnd, WM_USER_CREATEPAL, TRUE, 0); InvalidateRect (hwnd, NULL, TRUE);} else {MessageBox (hwnd, TEXT ( " NOT ENOUGH MEMORY "), SZAPPNAME, MB_OK | MB_ICONEXCLAMATION; RETURN 0; case IDM_APP_ABOUT: MessageBox (hwnd, TEXT ( "Dibble (c) Charles Petzold, 1998"), szAppName, MB_OK | MB_ICONEXCLAMATION); return 0;} // All the other WM_COMMAND messages are from the palette // items Any existing palette. Is deleted, and the cursor // is set to the hourglass. SendMessage (hwnd, WM_USER_DELETEPAL, 0, 0); SetCursor (LoadCursor (NULL, IDC_WAIT)); ShowCursor (TRUE);. // Notice that all messages for palette items are ended // with break rather than return This is to allow / / Additional processing later on. Switch (WPARAM) {CASE IDM_PAL_DIBTABLE: HPALETTE = DibpalDibTable (HDIB); Break; Case IDM_PAL_HALFTONE: HDC = GetDC (HWND); IF (HPALETTE = CREATEHALFTONEPALETTE (HDC)) FHALFTONEPALETTE = True; ReleaseDC (HWND, HDC); Break; Case IDM_PAL_ALLPURPURPOSE: HPALETTE = DibpalallPurpose (); Break case IDM_PAL_GRAY2: hPalette = DibPalUniformGrays (2); break; case IDM_PAL_GRAY3: hPalette = DibPalUniformGrays (3); break; case IDM_PAL_GRAY4: hPalette = DibPalUniformGrays (4); break; case IDM_PAL_GRAY8: hPalette = DibPalUniformGrays (8); break; case IDM_PAL_GRAY16 : hPalette = DibPalUniformGrays (16); break; case IDM_PAL_GRAY32: hPalette = DibPalUniformGrays (32); break; case IDM_PAL_GRAY64: hPalette = DibPalUniformGrays (64); break; case IDM_PAL_GRAY128: hPalette = DibPalUniformGrays (128); break; case IDM_PAL_GRAY256: hPalette = DibPalUniformGrays (256); break; case IDM_PAL_RGB222: hPalette = DibPalUniformColors (2,2,2); break; case IDM_PAL_RGB333: hPalette = DibPalUniformColors (3,3,3); break; case IDM_PAL_RGB444: hPalette = DibPalUniformColors (4,4 , 4); break; case IDM_PAL_RGB555: hPalette = DibPalUniformColors (5,5,5); break; case IDM_PAL_RGB666: hPalette = DibPalUniformColors (6,6,6); break; case IDM_PAL_RGB775: hPalette = DibPalUniformColors (7,7,5 ); Break; Case IDM_PAL_RGB757: HPALETTE = Dibpalunif ormColors (7,5,7); break; case IDM_PAL_RGB577: hPalette = DibPalUniformColors (5,7,7); break; case IDM_PAL_RGB884: hPalette = DibPalUniformColors (8,8,4); break; case IDM_PAL_RGB848: hPalette = DibPalUniformColors ( 8,4,8); break; case IDM_PAL_RGB488: hPalette = DibPalUniformColors (4,8,8); break; case IDM_PAL_OPT_POP4: hPalette = DibPalPopularity (hdib, 4); break; case IDM_PAL_OPT_POP5: hPalette = DibPalPopularity (hdib, 5) Break; Case IDM_PAL_OPT_POP6: HPALETTE = Dibpalpopularity (HDIB, 6); Break; Case IDM_PAL_OPT_MEDCUT: HPALETTE = Dibpalmediancut (HDIB, 6); Break;} // after processing pasy, the cursor // is restored to an arrow, the menu item is checked, and // the window is invalidated.hbitmap = dibcopytoddb (hdib, hwnd, hpalette); Showcursor (False); SetCursor (LoadCursor (NULL, IDC_ARROW); IF (HPALETTE) Palettemenu (HMENU, (WPARAM)); INVALIDATERECT (HWND, NULL, TRUE); RETURN 0; // this programer-defined message deletes an existing dib // in preparation for getting a new one. Invoked During // File Open Command, Edit Paste Command, And Others. Case WM_USER_DELETEDIB: IF (HDIB) {Dibdelete (HDIB); HDIB = NULL;} SendMessage (hwnd, wm_user_deletepal, 0, 0); Return 0; // this programer-defined message deletes an existing paste // in preparation for defining a new one. Case WM_USER_DELETEPAL: IF (HPALETTE) {DeleteObject (HPALETTE); HPALETTE = NULL; FHALFTONEPALETTE = FALSE; PALETTEMENU (HMENU, IDM_PAL_NONE);}} (hbitmap) deleteObject (hbitmap); Return 0; // Programmer-defined Message to create a new palette based on // a new dib. If wparam == true, Create A DDB AS Well. Case WM_USER_CREATEPAL: IF (HDIB) {HDC = Getdc (HWND); if ((RC_PALETTE & GetDeviceCaps (hdc, RASTERCAPS))!) {PaletteMenu (hMenu, IDM_PAL_NONE);} else if (hPalette = DibPalDibTable (hdib)) {PaletteMenu (hMenu, IDM_PAL_DIBTABLE);} else if (hPalette = CreateHalftonePalette (hdc )) {fhalftonePalette = true; Palettemenu (HMENU, IDM_PAL_HALFTONE);} ReleaseDC (HWND, HDC); IF ((BOOL) wParam HbitMap = DibcopyTodDB (HDIB, HWND, HPALETTE);} return 0; Case WM_Paint: HDC = BeginPaint (HWND, & PS); if (hPalette) {SelectPalette (hdc, hPalette, FALSE); RealizePalette (hdc);} if (hBitmap) {DisplayDib (hdc, fHalftonePalette DibBitmapHandle (hdib):? hBitmap, iHscroll, iVscroll, cxClient, cyClient, wShow, fHalftonePalette) Endpaint (hwnd, & ps); Return 0; Case WM_QueryneWPalette: if (! Hpalette) Return False; HDC = Getdc (HWND); SelectPalette (HDC, HPALETTE, FALSE); RealizePalette (HDC); InvalidateERECT (HWND, NULL, TRUE); ReleaseDC (HWND, HDC); Return True; Case WM_PALETTECHANGED: IF (! hpalette || (hwnd) wparam == hwnd) Break; HDC = getDC (hwnd); SelectPalette (HDC, HPALETTE, FALSE); RealizePalette (HDC); UpdateColors (HDC); ReleaseDC (HWND, HDC); Break; Case WM_DESTROY: IF (HDIB) DIBDelete (HDIB); IF (hbitmap) deleteObject (hbitmap); IF (HPALETTE) deleteObject (HPALETTE); PostQuitMessage (0); return 0;} return DefWindowProc (hwnd, message, wParam, lParam);} DIBBLE.RC (excerpt) // Microsoft Developer Studio generated resource script # include "resource.h" #include "afxres.h. "/// MenuDIBBLE MENU DISCARDABLE BEGIN POPUP" & File "BEGINMENUITEM" & Open ... / tCtrl O ", IDM_FILE_OPENMENUITEM" & Save ... / tCtrl S ", IDM_FILE_SAVEMENUITEM SEPARATORMENUITEM" & Print ... / tCtrl P ", IDM_FILE_PRINTMENUITEM SEPARATORMENUITEM "Propert & ies ...", IDM_FILE_PROPERTIESMENUITEM SEPARATORMENUITEM "E & xit", IDM_APP_EXITENDPOPUP "& Edit" BEGIN MENUITEM "Cu & t / tCtrl X", IDM_EDIT_CUTMENUITEM "& Copy / tCtrl C", IDM_EDIT_COPYMENUITEM "& Paste / tCtrl V", IDM_EDIT_PASTEMENUITEM "& Delete / tDelete ", IDM_EDIT_DELETEMENUITEM SEPARATOR MENUITEM" & Flip ", IDM_EDIT_FLIPMENUITEM" & Rotate ", IDM_EDIT_ROTATEENDPOPUP" & Show "BEGINMENUITEM" & Actual Size ", IDM_SHOW_NORMAL, CHECKEDMENUITEM" & Center ", IDM_SHOW_CENTERMENUITEM" & Stretch to Window ", IDM_SHOW_STRETCHMENUITEM" Stretch & Isotropically ", IDM_SHOW_ISOSTRETCHENDPOPUP" & Palett e "BEGINMENUITEM" & None ", IDM_PAL_NONE, CHECKEDMENUITEM" & Dib ColorTable ", IDM_PAL_DIBTABLEMENUITEM" & Halftone ", IDM_PAL_HALFTONEMENUITEM" & All-Purpose ", IDM_PAL_ALLPURPOSEPOPUP" & Gray Shades "BEGINMENUITEM" & 1. 2 Grays ", IDM_PAL_GRAY2MENUITEM" & 2. 3 Grays ", IDM_PAL_GRAY3MENUITEM" & 3. 4 grays ", IDM_PAL_GRAY4MENUITEM" & 4. 8 Grays ", IDM_PAL_GRAY8MENUITEM" & 5. 16 Grays ", IDM_PAL_GRAY16MENUITEM" & 6. 32 Grays ", IDM_PAL_GRAY32MENUITEM" & 7. 64 Grays ", IDM_PAL_GRAY64MENUITEM" & 8. 128 Grays ", IDM_PAL_GRAY128MENUITEM" & 9. 256 Grays ", IDM_PAL_GRAY256ENDPOPUP" & Uniform Colors "BEGINMENUITEM" & 1. 2R x 2G X 2b (8) ", IDM_PAL_RGB222MENUITEM" & 2. 3r x 3g x 3b (27) ", IDM_PAL_RGB333MENUITEM" & 3. 4R x 4g x 4b (64) ", IDM_PAL_RGB444MENUITEM" & 4. 5r x 5g x 5b (125) ", IDM_PAL_RGB555MenuItem "& 5. 6r x 6g x 6b (216)", IDM_PAL_RGB666MENUITEM "& 6. 7R x 7g x 5b (245)", IDM_PAL_RGB775MENUITEM "& 7. 7R x 5b x 7b (245)", IDM_PAL_RGB757MENUITEM "& 8. 5R x 7g x 7b (245) ", IDM_PAL_RGB577MENUITEM" & 9. 8R x 8G x 4B (256) ", IDM_PAL_RGB884MENUITEM" & A. 8R x 4G x 8B (256) ", IDM_PAL_RGB848MENUITEM" & B. 4R x 8G x 8B (256) ", IDM_PAL_RGB488ENDPOPUP" & Optimized "BEGINMENUITEM" & 1. Popularity Algorithm (4 bits) "IDM_PAL_OPT_POP4MENUITEM" & 2. Popularity Algorithm (5 bits) "IDM_PAL_OPT_POP5MENUITEM" & 3. Popularity Algorithm (6 bits) "IDM_PAL_OPT_POP6MENUITEM" & 4. Median Cut Algorithm ", I DM_PAL_OPT_MEDCUTENDENDPOPUP "Con & vert" BEGINMENUITEM "& 1. To 1 bit per pixel", IDM_CONVERT_01MENUITEM "& 2. To 4 bits per pixel", IDM_CONVERT_04MENUITEM "& 3. To 8 bits per pixel", IDM_CONVERT_08MENUITEM "& 4. To 16 bits per pixel", IDM_CONVERT_16MENUITEM " & 5. TO 24 BITS Per Pixel ", IDM_CONVERT_24MENUITEM" & 6. To 32 Bits Per Pixel ", IDM_CONVERT_32ENDPOPUP" & HELP "BeginMenuItem" & Help About ", IDM_APP_ABOUTENDEND /// AcceleratorDIBBLE ACCELERATORS DISCARDABLE BEGIN" C ", IDM_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT" O ", IDM_FILE_OPEN, VIRTKEY, CONTROL, NOINVERT" P ", IDM_FILE_PRINT, VIRTKEY, CONTROL, NOINVERT" S ", IDM_FILE_SAVE, VIRTKEY, CONTROL, NOINVERT "V", IDM_EDIT_PASTE, VIRTKEY, CONTROL, NOINVERTVK_DELETE, IDM_EDIT_DELETE, VIRTKEY, NOINVERT "X", IDM_EDIT_CUT, VIRTKEY, CONTROL, NOINVERTENDRESOURCE.H (excerpt) // Microsoft Developer Studio generated include file.// Used By Dibble.rc #define IDM_FILE_OPEN 40001 # define IDM_FILE_SAVE 40002 # define IDM_FILE_PRINT 40003 # define IDM_FILE_PROPERTIES 40004 # define IDM_APP_EXIT 40005 # define IDM_EDIT_CUT 40006 # define IDM_EDIT_COPY 40007 # define IDM_EDIT_PASTE 40008 # define IDM_EDIT_DELETE 40009 # define IDM_EDIT_FLIP 40010 # define IDM_EDIT_ROTATE 40011 # define IDM_SHOW_NORMAL 40012 # define IDM_SHOW_CENTER 40013 # define IDM_SHOW_STRETCH 40014 # define IDM_SHOW_ISOSTRETCH 40015 # define IDM_PAL_NONE 40016 # define IDM_PAL_DIBTABLE 40017 # define IDM_PAL_HALFTONE 40018 # define IDM_PAL_ALLPURPOSE 40019 # define IDM_PAL_GRAY2 40020 # define IDM_PAL_GRAY3 40021 # define IDM_PAL_GRAY4 40022 # define IDM_PAL_GRAY8 40023 # define IDM_PAL_GRAY16 40024 # define IDM_PAL_GRAY32 40025 #define IDM_PAL_GRAY64 40026 # define IDM_PAL_GRAY128 40027 # define IDM_PAL_GRAY256 40028 # define IDM_PAL_RGB222 40029 # define IDM_PAL_RGB333 40030 # define IDM_PAL_RGB444 40031 # define IDM_PAL_RGB555 40032 # define IDM_PAL_RGB666 40033 # define IDM_PAL_RGB775 40034 # define IDM_PAL_RGB757 40035 # define IDM_PAL_RGB577 40036 # define IDM_PAL_RGB884 40037 # define IDM_PAL_RGB848 40038 # define IDM_PAL_RGB488 40039 # define IDM_PAL_OPT_POP4 40040 # define IDM_PAL_OPT_POP5 40041 # define IDM_PAL_OPT_POP6 40042 # define IDM_PAL_OPT_MEDCUT 40043 # define IDM_CONVERT_01 40044 # define IDM_CONVERT_04 40045 # define IDM_CONVERT_08 40046 # define IDM_CONVERT_16 40047 # define IDM_CONVERT_24 40048 #define idm_convert_32 40049 # define IDM_APP_ABOUT 40050DIbble uses two other files, I will briefly explain them. Dibconv files (Dibconv.c and dibconv.h) Conversion between two different formats - for example, converted from 8 bits per status of 24 bits per status. Dibpal files (Dibpal.c and dibpal.h) establish a tangle. Dibble Maintains three important static variables in WNDPROC. These are the HDIB code of HDIB, call HPALETTTE code and call hbitmap's hbitmap code. HDIB is from Dibhelp; HPALETTE is from different functions or CREATEHALFTONEPALETTE functions from Dibpal; and hbitmap comes from dibhelp.c's dibcopyTodDB file and helps accelerate the screen display, especially in 256 color display mode. However, this code must be re-established whether there is a new "DIB Section" (obviously) or a different palette (not very obvious) in the program. Let us introduce Dibble from the functions and sequential. Archives load and storage DIBBLE can load DIB files in the WM_COMMAND message processing of idm_file_load and idm_file_save and store these files. During these message processing, DIBBLE launches the public archive dialog box by calling GetopenFileName and GetSaveFileName, respectively. For "File", "Save" function table command, Dibble only needs to call DibfileSave. For the "File", "Open" function table command, Dibble must first remove the previous HDIB, palette and dot matrix object. It completes this through a WM_USER_DELETEDIB message, which is handled by calling Dibdelete and DeleteObject. Then Dibble calls DibfileLoad in dibhelp, sends WM_USER_SETSCROLLS and WM_USER_CREATEPAL messages to reset the roll-up column and create a color panel. WM_USER_CREATEPAL information is also located in a new DDB location established from the DIB block. Display, rolling and printing DIBBLE's function table allows it to display DIB in the upper left corner of the display area, or display DIB in the middle of the display area, or to fill the display area, or to fill the display area as much as possible in the case where the aspect ratio is held. You can select the required options on Dibble's "Show" menu. Note that these four options in the showdib2 program in the previous chapter are identical. During the WM_PAINT message processing - also processing the "File", the "Print" command - DIBBLE Call DisplayDIB Versions. Note that DisplayDIB uses Bitblt and StretchBLT instead of using SetDibitStodevice and StretchDibits. During the WM_PAINT message processing, the dot matrix code passed to the function is created by the dibcopytoddb function and calls during WM_USER_CREATEPAL message processing. The DDB is compatible with the content of the video device. When processing the "File", "Print" command, Dibble calls DisplayDIB, where the DIB block code available from Dibhelp.c is from DibbitmapHandle Versions. Also note that Dibble reserves a static BOOL variable called FHAlftonePalette, and if you get HPALETTE from the CreateHalftonePalette, this variation is set to True. This will force the DISPLAYDIB letter to call StretchBLT instead of call Bitblt, even if DIB is specified in actual size display. The FHALFTONEPALETTE variable also causes the WM_PAINT process to pass the DIB block code to the DISPLAYDIB function, not the dot matrix code created by the dibcopytoddb. The use of the intermediate color tone disc is discussed in front of this chapter and showed in the ShowDib5 program. When using the paradigm for the first time, Dibble allows the DIB to be rolled in the display area. The rolling column is displayed only when the DIB is displayed in the actual size. When processing WM_PAINT, WndProc simply passes the current location of the rolling column to the DisplayDIB. scrapbook For the "CUT" and "Copy" function entries, Dibble calls DibcopyTopackedDIB in dibhelp. This group will get all DIB components and put them in a large memory block. For the first time you use some of the examples in this book, Dibble pastes DIB from the scrapbook. This includes calling the DibcopyFromPackedDib Veric and replaces the HDIB, toner and dot matrix stored in front of the window message processing program. Flip and rotation In addition to common "CUT", "Copy", "Paste" and "DELETE" options in Dibble, in addition to common "CUT", "FLIP" and "Rotate". The "FLIP" option enables the dot mapping around the horizontal axis - ie up and down reversal. The "Rotate" option rotates 90 degrees when the dot matrix is clockwise. Both of these functions need to access all DIB icons from a DIB to another (because two functions do not need to create new palette, so do not delete and re-establish toning plate). "Flip" function table options use Dibfliphorizontal Versions, this one is also located in dibble.c file. This card calls Dibcopy to get DIB precise copies. Then, enter the rehears of the original DIB to the new DIB, but copy these icons is to flip images up and down. Note that this card calls DibgetPixel and DibsetPixel. These are common in dibhelp.c (but not as fast as we want). To illustrate the difference between DibgetPixel and DibsetPixel written in Dibhelp.h, the DibrotaTeright function is used in the DibrotaTeright. However, it is first to note that the second parameter is set to TRUE when the function calls DIBCOPY. This leads to the width and height of DIBCOPY flip the original DIB to create a new DIB. In addition, the primitive dollar cannot be replicated by a dibcopy. However, the DibrotaTeright function has six different backps to copy the icon dollar from the original DIB to the new DIB-each corresponding to different DIB pins width (1 bit, 4-bit, 8-bit, 16) Bit, 24-bit and 32-bit yuan). Although more programming is included, the function is faster. Although "FLIP Horizontal" and "Rotate Right" option can be used to generate "FLIP VERTICAL", "Rotate LEFT" and "Rotate 180 °" feature, but all options will be performed directly. After all, Dibble is just a display. Simple palette; optimization palette In Dibble, you can select a different palette on the 256-color video display to display DIB. These are listed in the Dibble "Palette" function table. In addition to the intermediate color tone disk, the rest are created directly by Windows V. Call, all of which establish all functions of different color panels are provided by the Dibpal file shown by the program 16-24. Program 16-24 Dibpal file Dibpal.h / * --------------------------------------- ----------------------------------- dibpal.h header file for dibpal.c ------ -------------------------------------------------- -------------------- * / HPALETTE DibPalDibTable (HDIB hdib); HPALETTE DibPalAllPurpose (void); HPALETTE DibPalUniformGrays (int iNum); HPALETTE DibPalUniformColors (int iNumR, int iNumG, int iNumB); HPALETTE DibPalVga (void); HPALETTE DibPalPopularity (HDIB hdib, int iRes); HPALETTE Dibpalmediancut (HDIB HDIB, INT IRES); Dibpal.c / * ------------------------------------ ---------------------------------------- Dibpal.c - Palette-Creation functions c) Charles Petzold, 1998 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ --------------------------- * / # include / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------- DibpaldibTable: Creates a Palette from the dib color table ------------- -------------------------------------------------- -------------- * / HPALETTE DIBPALDIBTABLE (HPALETTE HPALETTE; INT I, InUM; Logpalette * PLP; RGBQUAD RGB; IF (0 == (Inum = DibnumColors (HDIB)) Return NULL; PLP = Malloc (SizeOf (INUM - 1) * SizeOf (PLP-> PALNUMENTRIES = Inum; For (i = 0; I PLP = Malloc (SizeOf (LogPalette) 246 * SizeOf (Paletteentry)); PLP-> Palversion = 0x0300; PLP-> PalNumentries = 247; // The fold loop Calculates 31 Gray Shades, But 3 of Them // Will Match The Standard 20 Colors For (i = 0, g = 0, incr = 8; g <= 0xff; i , g = incr) {plp-> palpalent [i] .pered = (byte) g; plp-> palpalent [i]. PEGREEN = (byte) g; plp-> palpalentry [i] .peblue = (byte) g; plp-> palpalentry [i] .peflags = 0; INCR = (INCR == 9? 8: 9); Of The Standard 20 Colors, And Another // 4 of The Standard 20 Colors, And Another // 4 of the Gray Shades Above. For (r = 0; r <= 0xff; r = 0x33) for (g = 0; g <= 0xFF; g = 0x33) for (b = 0; B <= 0xff; b = 0x33) {PLP -> palpalentry [i] .pered = (byte) r; plp-> palpalent [i] .pegreen = (byte) g; plp-> palpalent [i] .peblue = (byte) B; PLP-> Palpalent [i ] .peflags = 0; i ; hPALETTE = CREATEPALETTE (PLP); Free (plp); return hpalette;} / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------- DibpaluniformGrays: Creates a Palette of Inum Grays, Uniform Spaed ------------ -------------------------------------------------- -------------- * / HPALETTE DIBPALUNIFORMGRAYS (INT inum) {HPALETTE HPALETTE; INT I; Logpalette * PLP; PLP = Malloc (Sizeof (Logpalette) (Inum - 1) * SizeOf (Paletteentry)); PLP-> Palversion = 0x0300; PLP-> PALNUMENTRIES = inum; For (i = 0; i / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------- Dibpaluniformcolors: Creates A Palette of Inumr x inumg x inumb colors ------------ -------------------------------------------------- -------------- * / HPALETTE DIBPALUNIFORMCOLORS (INUMR, INUMG, INUMB) {HPALETTE HPALETTE; INT I, INUM, R, G, B; LOGPALETTE * PLP Inum = INUMR * InUMG * Inumb; PLP = Malloc (Sizeof (LogPalette) (Inum - 1) * SizeOf (PLETTEENTRY)); PLP-> Palversion = 0x0300; PLP-> PALNUMENTRIES = INUMR * Inumg * Inumb; i = 0; for (r = 0; r / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------- Dibpalvga: Creates A Palette Based on Standard 16 VGA Colors ------------ -------------------------------------------------- -------------- * / HPALETTE DIBPALVGA (VOID) {Static Rgbquad RGB [16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00}; HPALETTE HPALETTE; INT i; LOGPALETTE * PLP; PLP = Malloc (SizeOf (Logpalette) 15 * SizeOf (Paletteentry)); PLP-> Palversion = 0x0300; PLP-> PALNUMENTRIES = 16; For (i = 0; i <16; i ) {plp-> palpalent [i] .pered = RGB [i] .rgbred; plp-> palpalent [i] .pegreen = rgb [i] .rgbgreen; plp-> Palpalentry [i] .peblue = RGB [i] .rgbblue; plp-> palpalent [i] .peflags = 0;} HPALETTE = CREATEPALETTE (PLP); Free (PLP); Return Hpalette;} / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------------------------------------- -------------------------------------------------- ------ * / # define pack_rgb (r, g, b, Ires) ((int) | ((int) << (IRES)) | / ((int) (b) << ((Ires) (IRES)))))))))) / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- Accumcolorcounts: Fills Up Picount (Indexed by a Packed RGB Color) with counts of pixels of what color.- -------------------------------------------------- -------------------------- / Static Void Accumcolorcounts (HDIB HDIB, INT * Picount, INT IRES) {Int x, Y, CX, Cy; RGBQUAD RGB; CX = Dibwidth (HDIB); cy = dibheight (hdib); For (y = 0; y Rgb.rgbred >> = (8 - Ires); rgb.rgbgreen >> = (8 - Ires); RGB.RGBBLUE >> = (8 - IRES); picount [pack_rgb (rgb.rgbred, rgb.rgbgreen, rgb.rgbblue, IRES)];}} / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------- Dibpalpopularity: Popular Algorithm for Optimized Colors ---------------- -------------------------------------------------- ----------- * / HPALETTE Dibpalpopularity (HDIB HDIB, INT IRES) {HPALETTE HPALETTE; INT I, IAARRAYSIZE, IENTRY, ICOUNT, IINDEX, IMASK, R, G, B; INT * Picount; LogPalette * PLP; // Validity Checksif (DibbitCount (HDIB) <16) Return Null; IF (Ires <3 || Ires> 8) Return Null; // Allocate Array for Counting Pixel Colorsiarraysize = 1 << (3 * Ires); iMask = 1 << Ires) - 1; IF (null == (Picount = Calloc (IARRAYSIZE, SIZEOF (INT))))) Return Null; // Get The Color CountSaccumcolorcounts (HDIB, Picount, Ires); // SET UPA PALETTEPLP = Malloc (SizeOf (Logpalette) 235 * SizeOf (PLP-> Palversion = 0x0300; for (IENTRY = 0; IENTRY <236; IENTRY ) {for (i = 0, ICOUNT = 0; I PLP-> PALPALENTRY [IENTRY] .pered = (byte) r; plp-> palpalent [iTry] .pegreen = (byte) g; plp-> palpalent [ionTry] .peblue = (byte) b; plp-> palpalentry [ IENTRY] .peflags = 0; piCount [iIndex] = 0;} // On exit from the loop iEntry will be the number of stored entriesplp-> palNumEntries = iEntry; // Create the palette, clean up, and return the palette handlehPalette = CreatePalette (plp); free (picount); Free (PLP); Return hPALETTE; / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------- Structures Used for Implementing Median Cut Algorithm ----------------- -------------------------------------------------- --------- * / TypeDef struct // defines Dimension of a Box {int RMIN, RMAX, GMIN, GMAX, BMIN, BMAX;} MinMax; typef struct // for Compare Routine for Qsort {Int iBoxcount; rgbquad rgbboxAV;} Boxes; / * ---------------------------------------------- ----------------------------- FindaverageColor: in A Box --------------- -------------------------------------------------- ------------ * / Static Int FindaveRageColor (Int * Picount, MinMax MM, INT IRES, RGBQUAD * PrG) {INT R, G, B, IR, IG, IB, ITOTAL, ICOUNT // Initialize Some VariableSitotal = IR = Ig = IB = 0; // Loop Through colors in the BoxFor (r = mm.rmin; r <= mm.rmax; r ) for (g = mm.gmin; g <= Mm.gmax; g ) for (b = mm.bmin; b <= mm.bmax; b ) {/ get the number of pixels of what colorount = picount [pack_rgb (r, g, b, Ires)]; / / Weight the pixel count by the color valueir = iCount * r; ig = iCount * g; IB = iCount * B; ITOTAL = ICOUNT;} // Find the average colorPRGB-> rgbred = (byte) ((IR / ITOTAL) << (8 - Ires)); prgb-> rgbgreen = (byte) ((ig / itotal) << (8 - Ires)); prgb-> rgbblue = (byte) ((ib / ipotal) << (8 - IRES)); // Return The Total Number of Pixels in the Boxreturn}} / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------- Cutbox: Divide A Box in TWO ---------------- -------------------------------------------------- -------- * / Static Void Cutbox (int * Picount, INT IBOXCOUNT, MinMax MM, INT IRES, INT ILVEL, BOXES * PBOXES, INT * PIENTRY) {Int ICOUNT, R, G, B Download Adobe Reader MinMax mmnew; // if the box is empty, return IF (iBoxCount == 0) Return; // if the Nesting Level IS 8, or the Box is One Pixel, We're Ready // To Find The Average Color In The Box and Save It Along with // The Number of Pixels of That Color IF (ilevel == 8 || (mm.rmin == mm.rmax && mm.gmin == mm.gmax && mm.bmin == mm.bmax)) {pboxes [* pientry] .iboxcount = findaverageColor (Picount, MM, Ires, & Pboxes [* Pientry] .RGBboxav); (* Pientry) ;} // Otherwise, IF blue is the largest side, split itelse if ((mm.bmax - mm.bmin> mm.rmax - mm .Rmin) && (mm.bmax - mm.bmin> mm.gmax - mm.gmin)) {// Initialize a counter and loop through the blue sideicount = 0; for (b = mm.bmin; b IF (i count> = iboxcount / 2) Break; // if the next blue value will be the max, we're thereif (b == mm.bmax - 1) Break;} // cut the two} to cutbox is the New box count. // The third argument is the new min and max value. Mmnew = mm; mmnew.bmin = mm.bmin; mmnew.bmax = b; Cutbox (Picount, Icount, Mmnew, Ires, Ilevel 1, Pboxes, Pientry; Mmnew.bmin = b 1; mmnew.bmax = mm.bmax; Cutbox (Picount, iBoxCount - ICOUNT, MMNEW, IRES, ILVEL 1, Pboxes, Pientry);} // Otherwise, if Red Is The Largest Side, Split IT (Just Like Blue) Else IF (mm.rmax - mm.rmin > mm.gmax - mm.gmin) {iCount = 0; for (r = mm.rmin; r Mmnew.rmin = r 1; mmnew.rmax = mm.rmax; cutbox (picount, iBoxcount - iCount, Mmnew, Ires, Ilevel 1, Pboxes, Pientry);} // Otherwise, split along the green sizeelse {iCount = 0; for (g = mm.gmin; g IF (iCount> = iBoxcount / 2) Break; IF (g == mm.gmax - 1) Break;} mmnew = mm; mmnew.gmin = mm.gmin; mmnew.gmax = g; Cutbox (Picount, Icount, Mmnew, Ires, Ilevel 1, Pboxes, Pientry; Mmnew.gmin = g 1; mmnew.gmax = mm.gmax; Cutbox (Picount, Iboxcount - ICOUNT, MMNEW, IRES, ILVEL 1, Pboxes, Pientry;}} / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ------------------------------------------- -------------------------------------------------- -------- * / Static int compare (const boxes * pbox1, const boxes * pbox2) {return pbox1-> iboxcount - pbox2-> iboxcount;} / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------- Dibpalmediancut: Creates Palette Based on Median Cut Algorithm -------------- -------------------------------------------------- ------- * / HPalette Dibpalmediancut (HDIB HDIB, IRES) {Boxes Boxes [256]; HPALETTE HPALETTE; INT I, IAARRAYSIZE, ICOUNT, R, G, B, ITOTCOUNT, IDIM, IENTRY = 0 ; int * picount; logpalette * plp; MinMax mm; // Validity Checksif (Dibbitcount (HDIB) <16) Return Null; if (Ires <3 || Ires> 8) Return Null; // Accumulate Count of Pixel Colorsiarraysize = 1 << (3 * Ires); if (null == (Picount = Calloc (IRRAYSIZE, SIZEOF (int))))))))) Return Null; Accumcolorcounts (HDIB, Picount, Ires); // Find The Dimensions of the Total Boxidim = 1 << Ires; mm.rmin = mm.gmin = mm.bmin = IDIM - 1; mm.rmax = mm.gmax = mm.bmax = 0; ITOTCOUNT = 0; for (r = 0; R / On on t 2 2 2.. 2 p p p p p p p p p IENTRY VALUE WILL INDICATE The NUMBER OF NON-EMPTY BOXES. Cutbox (Picount, ITOTCOUNT, MM, IRES, 0, Boxes, & Intry; Free (Picount); // sort the RGB Table by the number of pixels for Each ColorQsort (Boxes, IEntry, SizeOf (Boxes), Compare; PLP = Malloc (IEentry - 1) * SizeOf (Paletteentry); IF PLP == NULL) RETURN NULL; PLP-> PALVERSION = 0x0300; PLP-> PALNUMENTRIES = IENTRY; for (i = 0; i HPALETTE = CREATEPALETTE (PLP); Free (PLP); Return Hpalette;} The first letter -DibpaldibTable- seems to be familiar. It establishes a palette according to the color table of DIB. This is similar to the PackedDibcreatePalette letter in the packedib.c used in the showdib3 in front of this chapter. In ShowDIB3, this function is only performed when DIB has color table. This function is useless in the 8-bit chamfered mode. In the preset, executing in 256 color display mode, dibble will first try to call DibpalDibTable to establish a color panel according to the DIB color table. If DIB does not have a color table, Dibble will call CREATEHALFTONEPALETTE and set the FHALFTONEPALETTE variable to true. This logic occurs during WM_USER_CREATEPAL message processing. Dibpal.c also performs a Funken DibpalalPurpose because this function is very similar to the CreateAllPurposepalette in ShowDIB4, so it looks familiar. You can also select this palette from the Dibble menu. The most interesting thing to display a dot pattern in 256 color mode is that you can directly control the color of Windows to display the image. If you select and display the toner, Winsows will use the color in this tuning disk instead of the color in other palette. For example, you can create a grayscale palette separately with a DibpalUniformgrays. The palette of the two grayscale is used only with 00-00-00 (black) and FF-FF-FF (white). Use this tuning disk to output images will provide high comparison "black and white" effects in some photos. 3 kinds of grayscale will be added in black and white, and two grayscale will be added using 4 grayscale. With 8 grayscale, you may see the obvious contour - the same grayscale, no regular spots, although it is clearly the closest color algorithm, but generally does not have any aesthetic judgment. Usually the 16 kinds of grayscale can significantly improve the image quality. It can eliminate all outlines in the use of 32 grayscale. At present, 64 grayscale is now the limit of most display devices. At this point, there is no marginal benefit to increase. There is no more than 64 grayscale, and there is any improvement on the 6-digit color resolution device. So far, for the 8-bit dollar display mode, there is a 16-bit element, 24-bit and 32-bit metallic DIB, we can design a universal palette (this is very effective for grayscale images, but usually not suitable for color images. Alternatively, use an intermediate color tone disc, which uses a mixed color display with a general-purpose color tuning disc. It should also be noted that when you select a 16-bit, 24-bit or 32-bit DIB in 8-bit element color mode, in order to display these images, the program will cost some time according to DIB content. To establish a GDI dot matrix object. If you do not need a tuning disk, the program will be less than the DIB to create a DDB (when you display the large 24-bit DIB with the 8-bit color mode, the performance of ShowDIB1 and ShowDIB4 can also see this difference) . Why is this? It searches close to color. Typically, when the 24-bit dib DIB is displayed (or converting DIB to DDB), the GDI must close each of the DIBs to a compared with one of still 20 colors. The only way to do this is to determine which static color is closest to the color color. This includes the distance between calculation of computing static colors in three-dimensional RGB colors. This will take some time, especially when there are millions of patins in the DIB image. At the time of establishing a 232-color tone disc, such as Dibble and SHOWDIB4, the general palette, you will increase the time from the color of the search to more than 11 times! GDI must now completely check 232 colors, not 20 kinds. That is why the entire job of DIB is displayed. The lesson here is to avoid displaying a 24-bit (or 16-bit, or 32-bit) DIB in the 8-bit metallic display mode. You should find a 256-color tone disc that is closest to the color range of DIB images to convert them to 8-bit dib. This is often referred to as "best color disc". When I study this problem, PAUL Heckbert's Evenly distributed Establishing a 256-color tone color disk is the easiest way to select a unified RGB color value, which is similar to the method in DibpalallPurpose. The advantage of this method is that you don't have to check the actual status in the DIB. This card is DibpalCreateuniform, which establishes a colorish disk based on the unified RGB three primary color index. A reasonable distribution includes 8th-order red and green, and the 4th-order blue (naked eye is more sensitive to blue). The palette is a collection of RGB color values. It is a total of 256% of red and green values 0x00, 0x24, 0x49, 0x6d, 0x92, 0xB6, 0xDB and 0xFF and blue value 0x00, 0x55, 0xaa and 0xFF. Color. Another possible unified distribution palette uses 6th-order red, green and blue. This color dish is red, green, and blue value of 0x00, 0x33, 0x66, 0x99, 0xcc, and 0xFF all possible combinations, the number of colors in the palette is 6 of 6, ie 216. Both options and several other options are provided by Dibble. "Popularity" algorithm The "Popular" algorithm is a relatively obvious solution of 256 color tone discs. What you have to do is to walk all the images in the drawings and find 256 most common RGB color values. These are the values you use in the palette. This is actually this algorithm in the DibpalPopularity function of Dibpal. However, if each color uses the entire 24-bit element, and assume that all colors need to be calculated, then the array will occupy 64MB memory. In addition, you can find that there is actually a 24-bit dyle value that is actually (or very few) in the dot mapping, so there is no such thing as a common color. To solve this problem, you can use only the most important N-bit in each red, green, and blue values - for example, 6-bit elements rather than 8 bits. Since most of the color scanners and video display cards have only 6 yuan resolution, this is more meaningful. This reduces the array to 256KB or 1MB of a more reasonable size. The total number of available colors can be reduced to 32,768 using only 5 bits. Typically, the use of 5-bit dollars is better than 6-bit metals. In this regard, you can use Dibble and some image colors from yourself. "Median Cut" algorithm DibpalMediancut in dibpal.c Execute Paul Heckbert's Median CUT Rate Algorithm. This algorithm is fairly simple in concept, but in the program code, it is more difficult than the Popularity algorithm, which is suitable for handback. Draw RGB color cubes. Each of the images is a point in this cube. Some points may represent multiple icons in the image. Find out three-dimensional squares including all the images in the image, find the maximum size of this block, and divide the block into two, each block includes the same number of icons. For these two squares, the same operation is performed. Now you have 4 squares, divide these 4 squares into 8, then divided into 16, 32, 64, 128 and 256. Now you have 256 squares, each block includes the same number of icons. Take the average value of the color value in each block and use the result for the palette. In fact, these blocks usually contain the number of icons. For example, there is usually more than a single point. This happens on black and white. Sometimes, some squares have no status at all. If so, you can save more squares, but I decided not to do this. Another optimal torch disk is called "Octree Quantization", which is proposed by Jeff Prosise and published in "Microsoft Systems Journal" in August 1996 (included in the MSDN CD). Conversion format Dibble also allows DIB to be converted from a format to another. This uses the DibconVert function in the DibConv file, as shown in the formula 16-25. Cheng - style 16-25 Dibconv file Dibconv.h / * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------- Dibconv.h header File for dibconv.c ------------- -------------------------------------------------- -------------- * / HDIB Dibconvert (HDIB HDIBSRC, INT IBITCOUNTDST); Dibconv.c / * ----------------------------------- ---------------------------------------- Dibconv.c - Converts Dibs from One Format To Another (C) Charles Petzold, 1998 ----------------------------------------- ----------------------------------- * / #include HDIB DibConvert (HDIB hdibSrc, int iBitCountDst) {HDIB hdibDst; HPALETTE hPalette; int i, x, y, cx, cy, iBitCountSrc, cColors; PALETTEENTRY pe; RGBQUAD rgb; WORD wNumEntries; cx = DibWidth (hdibSrc); cy = DibHeight (HDIBSRC); ibitcountsrc = dibbitcount (HDIBSRC); if (iBitCountSrc == iBitCountDst) return NULL; // DIB with color table to DIB with larger color table: if ((iBitCountSrc For (i = 0; i For (x = 0; x HDIBDST = Dibcreate (CX, CY, 8, WNUMENTRIES); for (i = 0; i <(int) Wnumentries; i ) {GetPaletteentries (HPALETTEENTEENTERES (HPALETTE, I, 1, & PE); RGB.RGBRED = pe.pered; RGB. RGBGreen = pe.pegreen; rgb.rgbblue = pe.peblue; rgb.rgbreserved = 0; DibsetColor (HDIBDST, I, & RGB); For (x = 0; x Else if (ibitcountdst == 1) {HDIBDST = Dibcreate (CX, CY, 1, 0); HPALETTE = Dibpaluniformgrays (2); For (i = 0; i <2; i ) {getPaletteentries (HPALETTE, I, 1, & PE); Rgb.rgbred = pe.pered; rgb.rgbgreen = pe.pegreen; rgb.rgbblue = pe.peblue; rgb.rgbreserved = 0; DibsetColor (HDIBDST, I, & RGB); For (x = 0; x Dibsetpixel (HDibdst, x, y, getnearestpaletteindex (HPALETTE, RGB (RGB.RGBRED, RGB.RGBGREEN, RGB.RGBBBLUE)));} deleteObject (HPALETTE);} // all non-monochrome Dibs to 4-bit Dibelse IF ibitcountsrc> = 8 && ibitcountdst == 4) {HDIBDST = Dibcreate (CX, CY, 4, 0); HPALETTE = Dibpalvga (); For (i = 0; i <16; i ) {getPaletteentries (HPALETTEEENTEENTRIES (HPALETTE, I, 1, & PE); RGB.RGBRED = pe.peged; rgb.rgbgreen = pe.pegreen; rgb.rgbblue = pe.peblue; RGB. RGBRESERVED = 0; DibsetColor (HDIBDST, I, & RGB); For (x = 0; x DibSetPixel (hdibDst, x, y, GetNearestPaletteIndex (hPalette, RGB (rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue)));} DeleteObject (hPalette);} // Should not be necessaryelsehdibDst = NULL; return hdibDst;} The DIB is converted from a format to another to require several different methods. To convert DIB with a color table into another also with a color table but have a larger dibly width DIB (i.e., the 1-bit dioss DIB is converted to a 4-bit or 8-bit dibly DIB, or will The 4-bit dioss DIB converts to 8-bit dib), which is required to create new DIB through call Dibcreate, and have a desired bit element with a desired bit and the number of color numbers in the original DIB. . Then the function copy the icon element and color table item. If the new DIB does not have a color table (ie, the bit number is 16, 24 or 32), then DIB only needs to be established in the new format, and the dibgetpixelcolor and dibsetpixelcolor are replicated from the existing DIB. The following situation may be more common: the existing DIB has no color table (ie, the number of seconds is 16, 24 or 32), while the new DIB is 8-bit per image. In this case, Dibconvert calls DibpalMediancut to establish an optimized palette for images. The color table of the new DIB is set to the RGB value in the palette. DibgetPixelcolor enables a color color from the existing DIB. Convert GetNearestPaletteIndex to a primitive in the 8-bit DIB, and store the dibsetpixel to DIB through call DibsetPixel. When DIB needs to be converted into monochrome DIB, establish a new DIB with a color table including two items - black and white -. In addition, GetnearestPaletteIndex helps to convert the colors in the existing DIB into a primitive 0 or 1. Similarly, when the DIB of 8 graphic dollars or more packets is converted to 4-bit dib, the DIB color table can be obtained from the DibPalvga letter, and GetNearestPaletteIndex also helps to calculate the iconic value. Although Dibble demonstrates how to start writing an image processing program, but the program is still not completed, we always think that there are still some features that have not been added. But unfortunately, we have to stop going to study these things now, and discuss something else.