TCHAR szAppName [] = TEXT "Fader" ;TCHAR szTitle [] = TEXT "Fader: Palette Animation Demo" ; This document is created with the unregistered version of CHM2PDF Pilot Simpo PDF Merge and S
Trang 1TCHAR szAppName [] = TEXT ("Fader") ;
TCHAR szTitle [] = TEXT ("Fader: Palette Animation Demo") ;
This document is created with the unregistered version of CHM2PDF Pilot
Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com
Trang 2void TimerRoutine (HDC hdc, HPALETTE hPalette)
Trang 3FADER displays the text string "Fade In And Out" all over its client area This text is initially displayed in white and appears invisible against the white background of the window By using palette animation, FADER gradually changes the color of the text to blue and then back to white, over and over again The text appears as if it's fading in and out
FADER creates a logical palette in its CreateRoutine function It needs only one entry of the palette and initializes the color to white red, green, and blue values all set to 255 In PaintRoutine (which, you'll recall, is called from
PALANIM after the logical palette has been selected into the device context and realized), FADER calls
SetTextColor to set the text color to PALETTEINDEX(0) This means that the text color is set to the first entry in
the palette table, which initially is white FADER then fills up its client area with the "Fade In And Out" text string At this time, the window background is white and the text is white and hence invisible
In the TimerRoutine function, FADER animates the palette by altering the PALETTEENTRY structure and passing
it to AnimatePalette The program initially decrements the red and green values by 4 for each WM_TIMER
message until they reach a value of 3 Then the values are incremented by 4 until they get back up to 255 This causes the color of the text to fade from white to blue and back to white again
The ALLCOLOR program shown in Figure 16-10 uses a single-entry logical palette to display all the colors that the video adapter can render It doesn't show them simultaneously, of course, but sequentially If your video adapter has
an 18-bit resolution (in which case it's capable of 262,144 different colors), at the rate of one color every 55
milliseconds you need spend only four hours staring at the screen to see all the colors!
Figure 16-10 The ALLCOLOR program
This document is created with the unregistered version of CHM2PDF Pilot
Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com
Trang 4TCHAR szAppName [] = TEXT ("AllColor") ;
TCHAR szTitle [] = TEXT ("AllColor: Palette Animation Demo") ;
static int iIncr ;
hPalette = CreatePalette (&lp) ;
// Save global for less typing
wsprintf (szBuffer, TEXT (" %02X-%02X-%02X "),
ppe->peRed, ppe->peGreen, ppe->peBlue) ;
TextOut (hdc, 0, 0, szBuffer, lstrlen (szBuffer)) ;
}
Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com
Trang 5void 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 value
pe.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) ;
This document is created with the unregistered version of CHM2PDF Pilot
Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com
Trang 6Structurally, ALLCOLOR is very similar to FADER In CreateRoutine, ALLCOLOR creates a palette with only
one palette entry whose color is set to black (the red, green, and blue fields of the PALETTEENTRY structure set to
0) In PaintRoutine, ALLCOLOR creates a solid brush using PALETTEINDEX(0) and calls FillRect to color the
entire client area with that brush
In TimerRoutine, ALLCOLOR animates the palette by changing the PALETTEENTRY color and calling
AnimatePalette I wrote ALLCOLOR so that the change in color is smooth First, the blue value is progressively
incremented When it gets to the maximum, the green value is incremented and then the blue value is progressively
decremented The incrementing and decrementing of the red, green, and blue color values is based on the iIncr variable This is calculated during CreateRoutine based on the value returned from GetDeviceCaps with the
COLORRES argument If GetDeviceCaps returns 18, for example, then iIncr is set to 4 the lowest value necessary
to obtain all the colors
ALLCOLOR also displays the current RGB color value in the upper left corner of the client area I originally added this code for testing purposes, but it proved to be useful so I left it in
Engineering Applications
In engineering applications, animation can be useful for the display of mechanical or electrical processes It's one thing
to display a combustion engine on a computer screen, but animation can really make it come alive and show its workings with much greater clarity
One possible process that's good for palette animation is showing fluids passing through a pipe This is a case where the image doesn't have to be strictly accurate in fact, if the image were accurate (as if you were looking at a
transparent pipe), it might be difficult to tell how the contents of the pipe were moving It's better to take a more symbolic approach here The PIPES program shown in Figure 16-11 is a simple demonstration of this technique It has two horizontal pipes in the client area The contents of the pipes move from left to right in the top pipe and from right to left in the bottom pipe
Figure 16-11 The PIPES program
Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com
Trang 7TCHAR szAppName [] = TEXT ("Pipes") ;
TCHAR szTitle [] = TEXT ("Pipes: Palette Animation Demo") ;
// Draw window background
SetRect (&rect, 0, 0, cxClient, cyClient) ;
hBrush = SelectObject (hdc, GetStockObject (WHITE_BRUSH)) ;
FillRect (hdc, &rect, hBrush) ;
// Draw the interiors of the pipes
This document is created with the unregistered version of CHM2PDF Pilot
Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com
Trang 8FillRect (hdc, &rect, hBrush) ;
DeleteObject (SelectObject (hdc, GetStockObject (WHITE_BRUSH))) ; }
// Draw the edges of the pipes
MoveToEx (hdc, 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) ;
Trang 9PIPES uses 16 palette entries for the animation, but you could probably get by with fewer At the minimum, all you really need are enough entries to show the direction of the flow Even three palette entries would be better than a static arrow
The TUNNEL program shown in Figure 16-12 is the piggiest program of this batch, using 128 palette entries for animation But the effect is worth it
Figure 16-12 The TUNNEL program
This document is created with the unregistered version of CHM2PDF Pilot
Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com
Trang 10TCHAR szAppName [] = TEXT ("Tunnel") ;
TCHAR szTitle [] = TEXT ("Tunnel: Palette Animation Demo") ;
plp->palPalEntry[i + 128].peRed = byGrayLevel ;
plp->palPalEntry[i + 128].peGreen = byGrayLevel ;
plp->palPalEntry[i + 128].peBlue = byGrayLevel ;
plp->palPalEntry[i + 128].peFlags = PC_RESERVED ;
Trang 11void PaintRoutine (HDC hdc, int cxClient, int cyClient)
rect.right = cxClient - i * cxClient / 255 ;
rect.bottom = cyClient - i * cyClient / 255 ;
hBrush = CreateSolidBrush (PALETTEINDEX (i)) ;
// Fill the rectangle and delete the brush
This document is created with the unregistered version of CHM2PDF Pilot
Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com
Trang 12TUNNEL uses 64 moving gray shades in the 128 palette entries from black to white and back to black to give the effect of traveling through a tunnel
Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com
Trang 13Palettes and Real-World Images
Of course, despite the fun we've been having displaying continuous shades of color and doing palette animation, the real purpose of the Palette Manager is to allow the display of real-world images under 8-bit video modes For the remainder of the chapter, we'll be exploring precisely that As you might have already anticipated, you must use palettes differently when using packed DIBs, GDI bitmap objects, and DIB sections The next six programs illustrate various techniques for using palettes with bitmaps
Palettes and Packed DIBs
Assisting us in the next three programs will be a set of functions that work with packed-DIB memory blocks These functions are in the PACKEDIB files shown in Figure 16-13
Figure 16-13 The PACKEDIB files
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 PackedDibGetBitsSize (BITMAPINFO * pPackedDib) ;
HPALETTE PackedDibCreatePalette (BITMAPINFO * pPackedDib) ;
This document is created with the unregistered version of CHM2PDF Pilot
Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com
Trang 14// 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 BITMAPFILEHEADER
bSuccess = ReadFile (hFile, &bmfh, sizeof (BITMAPFILEHEADER),
// Allocate memory for the packed DIB & read it in
dwPackedDibSize = bmfh.bfSize - sizeof (BITMAPFILEHEADER) ;
pbmi = malloc (dwPackedDibSize) ;
bSuccess = ReadFile (hFile, pbmi, dwPackedDibSize, &dwBytesRead, NULL) ; CloseHandle (hFile) ;
if (!bSuccess || (dwBytesRead != dwPackedDibSize))
Trang 15return abs (pPackedDib->bmiHeader.biHeight) ;
return pPackedDib->bmiHeader.biBitCount ;
}
int PackedDibGetRowLength (BITMAPINFO * pPackedDib)
{
return ((PackedDibGetWidth (pPackedDib) *
PackedDibGetBitCount (pPackedDib) + 31) & ~31) >> 3 ;}
PackedDibGetColorsUsed returns value in information header;
could be 0 to indicate non-truncated color table!
Trang 16iNumColors = 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) ; else
return PackedDibGetNumColors (pPackedDib) * sizeof (RGBQUAD) ;}
RGBQUAD * PackedDibGetColorTablePtr (BITMAPINFO * pPackedDib)
RGBQUAD * PackedDibGetColorTableEntry (BITMAPINFO * pPackedDib, int i)
Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com
Trang 17/* - PackedDibGetBitsSize can be calculated from the height and row length
if it's not explicitly in the biSizeImage field
-*/int PackedDibGetBitsSize (BITMAPINFO * pPackedDib)
plp = malloc (sizeof (LOGPALETTE) *
(iNumColors - 1) * sizeof (PALETTEENTRY)) ;
This document is created with the unregistered version of CHM2PDF Pilot
Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com
Trang 18The first function is PackedDibLoad, which takes as its single argument a file name and returns a pointer to a packed
DIB in memory All the other functions take this packed-DIB pointer as their first argument and return information about the DIB These functions are arranged in the file in a "bottom-up" order Each function uses information
obtained from earlier functions
I don't pretend that this is a "complete" set of functions that might be useful for working with packed DIBs I have not attempted to assemble a really extensive collection because I don't think that working with packed DIBs in this way
is a good approach This will be quite obvious to you when you try to write a function such as
dwPixel = PackedDibGetPixel (pPackedDib, x, y) ;
This kind of function involves so many nested function calls that it becomes horribly inefficient and slow I'll describe what I believe to be a better approach later in this chapter
Also, as you'll note, many of these functions require different processing for OS/2-compatible DIBs; thus, the
functions frequently check if the first field of the BITMAPINFO structure is the size of the BITMAPCOREHEADER structure
Of particular interest here is the final function, named PackedDibCreatePalette This function uses the color table in
the DIB to create a palette If the DIB does not have a color table (which means that the DIB has 16, 24, or 32 bits
per pixel), then no palette is created A palette created from the DIB color table is sometimes called the DIB's native
palette
The PACKEDIB files are put to use in SHOWDIB3, shown in Figure 16-14
Figure 16-14 The SHOWDIB3 program
Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com
Trang 19LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
TCHAR szAppName[] = TEXT ("ShowDib3") ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; wndclass.lpszMenuName = szAppName ;
This document is created with the unregistered version of CHM2PDF Pilot
Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com
Trang 20static 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") ;
cxClient = LOWORD (lParam) ;
cyClient = HIWORD (lParam) ;
Trang 21// Load the packed DIB into memory
SetCursor (LoadCursor (NULL, IDC_WAIT)) ;
0,
0,
0,
PackedDibGetHeight (pPackedDib), PackedDibGetBitsPtr (pPackedDib), pPackedDib,
Trang 23The window procedure in SHOWDIB3 maintains the packed-DIB pointer as a static variable that it obtains when it
calls the PackedDibLoad function in PACKEDIB.C during the File Open command During processing of this command, SHOWDIB3 also calls PackedDibCreatePalette to obtain a possible palette for the DIB Notice that
whenever SHOWDIB3 is ready to load in a new DIB, it first frees the memory of the previous DIB and also deletes the palette of the previous DIB The last DIB is eventually freed and the last palette is eventually deleted during processing the WM_DESTROY message
Processing of the WM_PAINT message is straightforward: If the palette exists, SHOWDIB3 selects it into the
device context and realizes it It then calls SetDIBitsToDevice, passing to the function information about the DIB
(such as width, height, a pointer to the DIB pixel bits) that it obtains from functions in PACKEDIB
Again, keep in mind that SHOWDIB3 creates a palette based on the color table in the DIB If there is no color table
in the DIB as is almost always the case with 16-bit, 24-bit, and 32-bit DIBs then no palette is created When the DIB is displayed in an 8-bit video mode, it's displayed with only the standard reserved 20 colors
There are two solutions to this problem The first is to simply use an "all-purpose" palette that can be applicable for a large number of images You can construct such a palette yourself The second solution is to dig into the pixel bits of the DIB and determine the optimum colors required to display the image Obviously this involves more work (both for the programmer and the processor), but I'll show you how to do it before this chapter has concluded
The All-Purpose Palette
This document is created with the unregistered version of CHM2PDF Pilot
Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com
Trang 24The SHOWDIB4 program, shown in Figure 16-15, constructs an all-purpose palette that it uses for displaying all DIBs loaded into the program SHOWDIB4 is otherwise very similar to SHOWDIB3
Figure 16-15 The SHOWDIB4 program
Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com
Trang 25LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
TCHAR szAppName[] = TEXT ("ShowDib4") ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
This document is created with the unregistered version of CHM2PDF Pilot
Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com
Trang 26CreateAllPurposePalette: Creates a palette suitable for a wide variety
of images; the palette has 247 entries, but 15 of them are
duplicates or match the standard 20 colors
-*/HPALETTE CreateAllPurposePalette (void)
// 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)
// The following loop is responsible for 216 entries, but 8 of
// them will match the standard 20 colors, and another
// 4 of them will match the gray shades above
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") ;
Trang 27cxClient = LOWORD (lParam) ;
cyClient = HIWORD (lParam) ;
// Load the packed DIB into memory
SetCursor (LoadCursor (NULL, IDC_WAIT)) ;
This document is created with the unregistered version of CHM2PDF Pilot
Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com
Trang 280,
0,
0,
PackedDibGetHeight (pPackedDib), PackedDibGetBitsPtr (pPackedDib), pPackedDib,
Trang 29This document is created with the unregistered version of CHM2PDF Pilot
Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com
Trang 30While processing the WM_CREATE message, SHOWDIB4 calls CreateAllPurposePalette It retains this palette
throughout the course of the program and destroys it during the WM_DESTROY message Because the program knows that the palette is always around, it needn't check for its existence while processing the WM_PAINT,
WM_QUERYNEWPALETTE, or WM_PALETTECHANGED messages
The CreateAllPurposePalette function seems to create a logical palette with 247 entries, which is more than the
236 entries in the system palette that programs normally have access to Indeed, it does, but this is just a matter of convenience Fifteen of these entries are either duplicated or will map to colors in the standard 20 reserved colors
CreateAllPurposePalette begins by creating 31 gray shades, with red, green, and blue values of 0x00, 0x09, 0x11,
0x1A, 0x22, 0x2B, 0x33, 0x3C, 0x44, 0x4D, 0x55, 0x5E, 0x66, 0x6F, 0x77, 0x80, 0x88, 0x91, 0x99, 0xA2, 0xAA, 0xB3, 0xBB, 0xC4, 0xCC, 0xD5, 0xDD, 0xE6, 0xEE, 0xF9, and 0xFF Notice that the first, last, and middle entries are in the standard 20 reserved colors Next the function creates colors with all combinations of red, green, and blue values of 0x00, 0x33, 0x66, 0x99, 0xCC, and 0xFF That's a total of 216 colors, but eight of them duplicate colors in the standard 20, and another four duplicate previously calculated gray shades Windows will not
put duplicate entries in the system palette if you set the peFlags field of the PALETTEENTRY structure to 0
Obviously, a real program that didn't wish to calculate optimum palettes for 16-bit, 24-bit, or 32-bit DIBs would probably still continue to use the DIB color table for displaying 8-bit DIBs SHOWDIB4 does not do this but instead uses its all-purpose palette for everything This is because SHOWDIB4 is a demonstration program, and you can use
it to compare SHOWDIB3's display of 8-bit DIBs If you look at some color DIBs of people, you'll probably
conclude that SHOWDIB4 does not have sufficient colors for the accurate rendering of flesh tones
Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com
Trang 31If you experiment with the CreateAllPurposePalette function in SHOWDIB4, perhaps by reducing the size of the
logical palette to just a few entries, you'll discover that when a palette is selected into a device context, Windows will use only the colors in the palette and none of the colors from the standard 20-color palette
The Halftone Palette
The Windows API includes an all-purpose palette that programs can obtain by calling CreateHalftonePalette You can use this in the same way you used the palette obtained from CreateAllPurposePalette in SHOWDIB4, or you can use it in conjunction with the bitmap stretching mode set with SetStretchBltMode known as HALFTONE The
SHOWDIB5 program in Figure 16-16 demonstrates how to use the halftone palette
Figure 16-16 The SHOWDIB5 program.
This document is created with the unregistered version of CHM2PDF Pilot
Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com
Trang 32LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
TCHAR szAppName[] = TEXT ("ShowDib5") ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
Trang 33LRESULT 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") ;
cxClient = LOWORD (lParam) ;
cyClient = HIWORD (lParam) ;
Trang 34
// Load the packed DIB into memory
SetCursor (LoadCursor (NULL, IDC_WAIT)) ;
// Select and realize halftone palette
SelectPalette (hdc, hPalette, FALSE) ;
Trang 35This document is created with the unregistered version of CHM2PDF Pilot
Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com
Trang 36The SHOWDIB5 program is similar to SHOWDIB4 in that it doesn't use the color table in the DIB but instead uses
a palette that is appropriate for a wide range of images SHOWDIB5 uses the logical palette supplied by Windows
for this purpose, a handle to which can be obtained from the CreateHalftonePalette function
This halftone palette is hardly more sophisticated than the palette created by the CreateAllPurposePalette function
in SHOWDIB4 And indeed, if you use it by itself, the results will be similar However, if you call these two
functions,
SetStretchBltMode (hdc, HALFTONE) ;
SetBrushOrgEx (hdc, x, y, NULL) ;
where x and y are the device coordinates of the upper left corner of the DIB, and if you display the DIB with
StretchDIBits rather SetDIBitsToDevice, the results will surprise you Color flesh tones are much more accurate
than with CreateAllPurposePalette or with CreateHalftonePalette used without setting the bitmap stretching
mode Windows uses a type of dithering pattern with the colors of the halftone palette to better approximate the colors of the original image on 8-bit video boards As you might expect, the drawback is that it takes more
processing time
Indexing Palette Colors
Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com
Trang 37The time has come to tackle the fClrUse argument to SetDIBitsToDevice, StretchDIBits, CreateDIBitmap,
SetDIBits, GetDIBits, and CreateDIBSection Normally, you set this argument to DIB_RGB_COLORS, which
equals 0 However, you can also set it to DIB_PAL_COLORS In this case, the color table in the BITMAPINFO structure is assumed to consist not of RGB color values but of 16-bit indices into a logical palette This logical palette
is the one currently selected in the device context given as the first argument to the function Indeed, in
CreateDIBSection, the use of DIB_PAL_COLORS is the only reason that you would need to specify a non-NULL
device context handle as the first argument
What does DIB_PAL_COLORS do for you? It gives you some performance improvement Consider an 8-bit DIB
that you're displaying in an 8-bit video mode by calling SetDIBitsToDevice Windows must first do a nearest-color
search of all the colors in the DIB color table with the colors available on the device It can then set up a little table that lets it map DIB pixel values to the device pixels At most, this means 256 nearest-color searches, but they can be skipped if the DIB color table contains instead indices into a logical palette selected in a device context
The SHOWDIB6 program shown in Figure 16-17 is similar to SHOWDIB3 except that it uses palette indices
Figure 16-17 The SHOWDIB6 program
This document is created with the unregistered version of CHM2PDF Pilot
Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com
Trang 38LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
TCHAR szAppName[] = TEXT ("ShowDib6") ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
Trang 39LRESULT 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") ;
cxClient = LOWORD (lParam) ;
cyClient = HIWORD (lParam) ;
This document is created with the unregistered version of CHM2PDF Pilot
Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com
Trang 40// Load the packed DIB into memory
SetCursor (LoadCursor (NULL, IDC_WAIT)) ;
// Create the palette from the DIB color table
hPalette = PackedDibCreatePalette (pPackedDib) ;
// Replace DIB color table with indices