Windows NT Systems Programming
[ Home
| Syllabus |Course Notes]
Palettes, Bitmaps (Chapter 12)
Video Images
Ditial Motion Video has many simlarities with digital audio,
but also significant technological, physiological and psychological difference
- Much lower sample rate (30 frames per second to acheive TV
quality motion)
- One video frame (picture) is a sample (ranging from several
hundreds of x,y points approaching 2k x 2k)
- Thus one sample at 100 by 100 resolution and 8 bits of color per
PIXEL = 10,000 bytes of information
- 1000 by 1000 and 24 bits of color (typical computer monitor) -
3,000,000 bytes of information
- Much higher bits/sample because of two dimensional nature of the
sample
- 100 by 100 by 8b/pixel by 15 fps = 150,000 bytes/sec
- 1000 x 1000 x 24b/pixel x 30 fps = 90 Megabytes/sec
- Compression is thus common
- space compression within a frame (runlength encoding, block
encoding, quad tree)
- time compress between frames
- or both
- Hardware compression of common standards
- We will focus on handling a single frame
BitMapped Displays
Display Technology and Video Drivers.
- Vector, Raster, PIXEL displays
- VECTOR: Drew pictures as a set of vectors on the screen
if image is simple, don't need to draw background, could be very fast
- RASTER: Draws pictures a scan line at a time
drawing time independent of amout of information.
- PIXEL: draws PIXELS directly (plasma panel displays)
- BITMAPPED DISPLAY: pioneered by XEROX PARC, draw images by
setting PIXELS in a BITMAP which is displayed on the screen. Display needing constant
refresh use frame buffer in video RAM.
- Can have "extra" frame buffers which can be built
or loaded while a "current" buffer is displayed then switch pointer to
new buffer when ready.
- Performance enhanced by minimizing data copies to/from frame
buffers.
The Color Dimension
- Monochrome displays (1 bit per PIXEL)
- Could Dither to get "grayscale" - Relies on integrating
properties of the human visual system (physiology)
newpaper pictures (halftone).
Dithering is a method to produce an "average" tone value over an area by
combining tones from a limited palette in spatial proportion to the average value. (e.g.
half white and half black will give the impression of medium gray is dispersed uniformally
over the area.
- Color is usually three tones (Red, Green Blue (RGB) mixed within
a pixel to produce color. or chosen from a limited palette of colors.
- Early Color was 16 colors
- Common is 256 colors (8 bits).
- Emerging 24 bit color (8 bits each for RGB).
Color Palettes
- If 256 colors, then must choose which colors to put in this
limited palette.
- Further complicated by sharing of palette among all applications
drawing to screen.
- BY default, only 20 colors are used
- To access additional colors, must utilize the palette.
- COLORREF: 24 bit color value consisting of 8 bit Red, Green, Blue
values (RGB).
- RGB(0,0,0) is black
- RGB(255,255,255) is white
- With 24 bit color video cards, RGB is directly translated to
correct color.
- Palettized devices can display many colors but only a limited
number at a time (video memory limitation not a device limitation)
- Standard VGA is 6 bits of color per RGB = 18 bits 262, 144
colors, but at 640 by 480, only 4 bits per pixel of color (16 colors)
- Modern is 16 million colors, but only 256 at a time in hardware
color palette. PIXEL value is index into this palette.
- Windows preprograms 20 static colors into a 256 color
palette AND THESE ARE THE ONLY ONES AVAILABLE BY DEFAULT
Mapping onto the Palette.
Pens: Map COLORREF to nearest static color
Brushes: COLORREF is dithered using static colors
How to Access the other 236 colors? (Given that it is shared
among all applications?)
Logical Palettes
- System Palette = hardward palette
- Realizing a palette: Can transfer colors from a logical
palette to the unused entries in the system palette.
- If more than one application uses a logical palette, the GDI
arbitrates.
- If all logical palettes together use more than 236 colors,
priority is assigned according to Z-order and in the order of appearance in the
logical palette( see below).
- Savings if match static colors or background palettes use colors
already chosen by foreground windows, if still not enough, then picks closest among
the 256 already allocated.
- HalftonePalette: a set of 256 generic colors suitable for many
images: contains all colors in 6 by 6 by 6 color cube (6**3 colors = 216 colors), plus
array of gray.
- OR can create custom palette if you want to favor certain colors
over others.
Creating Custom Logical Palettes
First fill in the LOGPALETTE data structures.
typedef struct tagLOGPALETTE {
WORD palVersion;
WORD palNumEntries;
PALETTEENTRY palPalEntry[1];
} LOGPALETTE;
and
typedef struct tagPALETTEENTRY { // pe
BYTE peRed;
BYTE peGreen;
BYTE peBlue;
BYTE peFlags;
} PALETTEENTRY;
- RGB values are 8 bit
- Flags: 0 is normal
- Most important colors should appear first
- Need to allocate the actual memory usage depending on
palNumEntries. eg.
struct {
LOGPALETTE lp;
PALETTEENTRY ape[31];
} pal;
LOGPALETTE* pLP = (LOGPALETTE*) &pal;
pLP->palVersion = 0x300;
pLP->palNumEntries = 32;
// would allocate 32 colors in this palette
// after setting values for all 32 entries, create a palette with
m_palette.CreatePalette(pLP);
Realizing a Palatte
- Associate Palette with a device context using SelectPalette
member function of DC
- Default palette is one containing the static colors
- RealizePalatte maps colors from logical palette to system
palette.
- Can have both foreground and background palettes, background used
for inactive views ina multiple view document
Drawing with a Logical Palette
- RGB uses only static colors
- PALETTERGB uses nearest palette color
- PALETTEINDEX is an index into logical palette (fastest)
WM_QUERYPALETTE and WM_PALETTECHANGED
Two Messages sent about palettes:
- WM_QUERYPALETTE: setn by parent to a child which receives focus
Allows foreground window to assert priority in system color palette
tests for changes so can avoid repaints
- WM_PALETTECHANGED: sent to all top-level windows when a palette
realization changes the system palette.
Enables background windows to pick best of remaining slots for their color palettes.
In either case, the normal response is to realize the palette
and repaint.
Palette Demo
class CMainWindow : public CFrameWnd
{
private:
CPalette m_palette;
void DoGradientFill (CDC*, CRect*);
void DoDrawText (CDC*, CRect*);
public:
CMainWindow ();
protected:
afx_msg int OnCreate (LPCREATESTRUCT);
afx_msg BOOL OnEraseBkgnd (CDC*);
afx_msg void OnPaint ();
afx_msg BOOL OnQueryNewPalette ();
afx_msg void OnPaletteChanged (CWnd*);
DECLARE_MESSAGE_MAP ()
};
- F1: Called before OnPaint to repaint background (actually by
BeginPaint at begining of handling the WM_Paint message)
Implementation
#define FONTHEIGHT 72
int CMainWindow::OnCreate (LPCREATESTRUCT lpcs)
{
if (CFrameWnd::OnCreate (lpcs) == -1)
return -1;
CClientDC dc (this);
if (dc.GetDeviceCaps (RASTERCAPS) & RC_PALETTE) {
struct {
LOGPALETTE lp;
PALETTEENTRY ape[63]; // 64 shades of blue
} pal;
LOGPALETTE* pLP = (LOGPALETTE*) &pal;
pLP->palVersion = 0x300;
pLP->palNumEntries = 64;
for (int i=0; i<64; i++) {
pLP->palPalEntry[i].peRed = 0;
pLP->palPalEntry[i].peGreen = 0;
pLP->palPalEntry[i].peBlue = 255 - (i * 4); // From Black to Blue
pLP->palPalEntry[i].peFlags = 0;
}
m_palette.CreatePalette (pLP); // Create this blue palette
}
return 0;
}
BOOL CMainWindow::OnEraseBkgnd (CDC* pDC)
{
CRect rect;
GetClientRect (&rect);
// return true; // this returns without painting a new background - so you get a transparent window - try it
CPalette* pOldPalette;
if ((HPALETTE) m_palette != NULL) {
pOldPalette = pDC->SelectPalette (&m_palette, FALSE);
pDC->RealizePalette ();
}
DoGradientFill (pDC, &rect);
if ((HPALETTE) m_palette != NULL)
pDC->SelectPalette (pOldPalette, FALSE);
return TRUE;
}
void CMainWindow::OnPaint ()
{
CRect rect;
GetClientRect (&rect);
CPaintDC dc (this);
DoDrawText (&dc, &rect);
}
BOOL CMainWindow::OnQueryNewPalette ()
{
if ((HPALETTE) m_palette == NULL) // Shouldn't happen, but
return 0; // let's be sure
CClientDC dc (this);
CPalette* pOldPalette = dc.SelectPalette (&m_palette, FALSE);
UINT nCount;
if (nCount = dc.RealizePalette ())
Invalidate ();
dc.SelectPalette (pOldPalette, FALSE);
return nCount;
}
void CMainWindow::OnPaletteChanged (CWnd* pFocusWnd)
{
if ((HPALETTE) m_palette == NULL) // Shouldn't happen, but
return; // let's be sure
if (pFocusWnd != this) {
CClientDC dc (this);
CPalette* pOldPalette = dc.SelectPalette (&m_palette, FALSE);
if (dc.RealizePalette ())
Invalidate ();
dc.SelectPalette (pOldPalette, FALSE);
}
}
void CMainWindow::DoGradientFill (CDC* pDC, CRect* pRect)
{
CBrush* pBrush[64];
for (int i=0; i<64; i++) // Create 64 blue brushes
pBrush[i] = new CBrush (PALETTERGB (0, 0, 255 - (i * 4)));
// This requests many shades of blue brushes, but logical palette created before must have them assigned
int nWidth = pRect->Width ();
int nHeight = pRect->Height ();
CRect rect;
for (i=0; i<nHeight; i++) {
rect.SetRect (0, i, nWidth, i + 1); // rectangle = one line
pDC->FillRect (&rect, pBrush[(i * 63) / nHeight]); // fill with nearest blue brush
}
for (i=0; i<64; i++)
delete pBrush[i]; // prevent memory leaks
}
void CMainWindow::DoDrawText (CDC* pDC, CRect* pRect)
{
CFont font;
int nHeight = -((pDC->GetDeviceCaps (LOGPIXELSY) * FONTHEIGHT) / 72);
font.CreateFont (nHeight, 0, 0, 0, FW_BOLD, TRUE, 0, 0,
DEFAULT_CHARSET, OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS,
DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Times New Roman");
pDC->SetBkMode (TRANSPARENT);
//pDC->SetBkColor(RGB(255,0,255)); // use this to change background around text object
pDC->SetTextColor (RGB (255, 255, 255)); // Display white text
CFont* pOldFont = pDC->SelectObject (&font);
pDC->DrawText ("Hello, MFC", -1, pRect, DT_SINGLELINE | DT_CENTER |
DT_VCENTER);
pDC->SelectObject (pOldFont);
}
- F2: See if Device supports palettized color modes, otherwise why
bother
- F3: Number of palette colors which have changed in the system palette.
if 0 don't need to repaint
- F4: window which just realized the palette and caused this message
- F5: Avoid possible infinite loops or unnecessary recursion.
- F6: negative means use actual character height, excluding extra space
at top and bottom, positive height includes spacing
- F7: Number of PIXELS per logical inch along the height
- F8: Italics
- F9: Leaves background alone so previously drawn in OnEraseBkgnd is
kept
BitMaps
- Device Dependent Bitmaps (DDB)
- Simplest
- Most limiting
- fully encapsulated in MFC
- Device Indepencent Bitmap (DIB)
- DIB section
DDB and CBitmap Class
- Requires device context for properties of bitmap
- Can draw into it with a memory device context
CClientDC dcScreen (this);
CBitmap bitmap;
bitmap.CreateCompatibleBitmap(&dcScreen, 100, 100);
CDC dcMem;
dcMem.CreateCompatibleDC(&dcScreen);
CBrush brush(RGB(0,0,255));
CBitmap* pOldBitmap = dcMem.SelectObject(&bitmap);
dcMem.FillRect(CRect(0,0,100,100), &brush);
dcMem.SelectObject(pOldBitmap);
- F10: device context whcih describces the drawing properties of the
current window.
- F11: Makes this DDB compatible with the current screen device
chracteristics
- F12: Now makes a device context for drawing on the new memory bit map
-
BLITting
Need to block transfer bitmaps
Can't simply select a bit map into a screen (nonmemory) DC
- BitBlt: transfers a block of bits from one DC to another
dcScreen.BitBlt(0,0,100,100,&dcMem,0,0,SRCCOPY);
// where first four are coordinates of screen region
// second pair of 0's are corrdinates in dcMem bitmap to start
// SRCCOPY means bits are unchanged.
- StretchBlt: allows resizing of the bit block
In addition to parameters for BitBlt has size of from region as well
Can get properties of a bitmap by calling the GetObject
function.
typedef struct tagBITMAP {
LONG bmType; // always 0
LONG bmWidth; // in PIXELs
LONG bmHeight;
LONG bmWidthBytes; // length in bytes of one line
WORD bmPlanes; // number of color planes
WORD bmBitsPixel; // number of bits for each color
LPVOID bmBits; // pointer to actual bits NULL if DDB
} BITMAP;
Loading Bitmap Resources
- In resource file
IDR_LOGOIMAGE BITMAP Logo.bmp
- In program, load this resource
CBitmap bitmap;
bitmap.LoadBitmap(IDR_LOGOIMAGE);
Copyright chris wild 1997.
For problems or questions regarding this web contact [Dr. Wild].
Last updated: November 10, 1997.